通过调用从后台线程C#线程问题 [英] c# Thread issue using Invoke from a background thread
问题描述
我有线程,它处理一些分析工作。
私有静态无效ThreadProc的(obj对象)
{
VAR电网=(DataGridView的)目标文件;
的foreach(的DataGridViewRow行grid.Rows)
{
如果(Parser.Get preparationByClientNameForSynonims(row.Cells [$ P $页。Value.ToString())!= NULL)
UpdateGridSafe(网格,row.Index,1);
Thread.sleep代码(10);
}
}
我要安全地更新我的GridView的循环,所以我用经典的方式:
私人委托无效UpdateGridDelegate(DataGridView的网格,诠释rowIdx,int型的);
公共静态无效UpdateGridSafe(DataGridView的网格,诠释rowIdx,整型)
{
如果(grid.InvokeRequired)
{
grid.Invoke(新UpdateGridDelegate(UpdateGridSafe),新的对象[] {格,rowIdx,类型});
}
其他
{
如果(类型== 1)
grid.Rows [rowIdx] .Cells [$ P $页] Style.ForeColor = Color.Red。
如果(类型== 2)
grid.Rows [rowIdx] .Cells [$ P $页] Style.ForeColor = Color.ForestGreen。
}
}
但是,当我进入UpdateGridSafe,该程序挂起。
在调试器,我看到grid.Invoke不调用UpdateGridSafe。请帮助 - 什么是错的。
?修改
经典线程创建code
线程t =新主题(新ParameterizedThreadStart(ThreadProc的));
t.Start(dgvSource);
t.Join();
的MessageBox.show(完成,信息);
您有一个僵局。您t.Join挡住了GUI线程,直到ThreadProc的完成。 ThreadProc的被阻塞,等待t.Join完成,因此它可以做到的调用。
为code
线程t =新主题(新ParameterizedThreadStart(ThreadProc的));
t.Start(dgvSource);
t.Join(); < ---僵局程序
的MessageBox.show(完成,信息);
好code
backgroundWorker1.RunWorkerAsync
私人无效backgroundWorker1_DoWork(对象发件人,
DoWorkEventArgs五)
{
VAR电网=(DataGridView的)目标文件;
的foreach(的DataGridViewRow行grid.Rows)
{
如果(Parser.Get preparationByClientNameForSynonims(row.Cells [$ P $页。Value.ToString())!= NULL)
UpdateGridSafe(网格,row.Index,1);
//不需要这个了Thread.Sleep(10);
}
}
私人无效backgroundWorker1_RunWorkerCompleted(
对象发件人,RunWorkerCompletedEventArgs E)
{
的MessageBox.show(完成,信息);
}
修改
还可以使用的BeginInvoke,而不是调用。这样,你的工作线程没有阻止每次更新GUI的时间。
参考
I've got thread, which processes some analytic work.
private static void ThreadProc(object obj)
{
var grid = (DataGridView)obj;
foreach (DataGridViewRow row in grid.Rows)
{
if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)
UpdateGridSafe(grid,row.Index,1);
Thread.Sleep(10);
}
}
I want safely update my gridView at loop, so I use classic way:
private delegate void UpdateGridDelegate(DataGridView grid, int rowIdx, int type);
public static void UpdateGridSafe(DataGridView grid, int rowIdx, int type)
{
if (grid.InvokeRequired)
{
grid.Invoke(new UpdateGridDelegate(UpdateGridSafe), new object[] { grid, rowIdx, type });
}
else
{
if (type == 1)
grid.Rows[rowIdx].Cells["Prep"].Style.ForeColor = Color.Red;
if (type==2)
grid.Rows[rowIdx].Cells["Prep"].Style.ForeColor = Color.ForestGreen;
}
}
But when I enter UpdateGridSafe, the program hangs.
In the debugger, I see that grid.Invoke doesn't invoke UpdateGridSafe. Please help - what's wrong?
EDIT
Classic thread create code
Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
t.Start(dgvSource);
t.Join();
MessageBox.Show("Done", "Info");
You have a deadlock. Your t.Join is blocking the GUI thread until ThreadProc is done. ThreadProc is blocked waiting for t.Join to finish so it can do the Invokes.
Bad Code
Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
t.Start(dgvSource);
t.Join(); <--- DEADLOCK YOUR PROGRAM
MessageBox.Show("Done", "Info");
Good Code
backgroundWorker1.RunWorkerAsync
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
var grid = (DataGridView)obj;
foreach (DataGridViewRow row in grid.Rows)
{
if (Parser.GetPreparationByClientNameForSynonims(row.Cells["Prep"].Value.ToString()) != null)
UpdateGridSafe(grid,row.Index,1);
// don't need this Thread.Sleep(10);
}
}
private void backgroundWorker1_RunWorkerCompleted(
object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done", "Info");
}
EDIT
Also use BeginInvoke instead of Invoke. That way your worker thread doesn't have to block every time you update the GUI.
Reference
Avoid Invoke(), prefer BeginInvoke()
这篇关于通过调用从后台线程C#线程问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!