c#使用后台线程调用的线程问题

And*_*kov 5 .net c# multithreading

我有线程,它处理一些分析工作.

   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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

我想在循环中安全地更新我的gridView,所以我使用经典方式:

    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;

        }
    }
Run Code Online (Sandbox Code Playgroud)

但是当我进入UpdateGridSafe时,程序会挂起.

在调试器中,我看到grid.Invoke不会调用UpdateGridSafe.请帮忙 - 出了什么问题?

编辑

经典线程创建代码

        Thread t = new Thread(new ParameterizedThreadStart(ThreadProc));
        t.Start(dgvSource);
        t.Join();
        MessageBox.Show("Done", "Info");
Run Code Online (Sandbox Code Playgroud)

Jon*_*len 6

你有一个僵局.你的t.Join阻止了GUI线程,直到ThreadProc完成.ThreadProc被阻塞等待t.Join完成所以它可以执行Invokes.

糟糕的代码

    Thread t = new Thread(new ParameterizedThreadStart(ThreadProc)); 
    t.Start(dgvSource); 
    t.Join();  <--- DEADLOCK YOUR PROGRAM
    MessageBox.Show("Done", "Info"); 
Run Code Online (Sandbox Code Playgroud)

好的代码

   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"); 
}
Run Code Online (Sandbox Code Playgroud)

编辑

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()