C # Problem using Invoke from background thread

I have a thread that handles 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 to safely update the gridView in a loop, so I use the 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 freezes.

In the debugger, I see that grid.Invoke does not call 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");
+5
source share
5 answers

You have a dead end. Your t.Join blocks the GUI thread until ThreadProc is executed. ThreadProc is blocked, waiting for t.Join to complete so that it can execute 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

BeginInvoke Invoke. , , .

Invoke(), BeginInvoke()

+6

, . , . .

Invoke, . Join, . , .

, Join MessageBox. MessageBox .

void NotifyDone() {
    if( InvokeRequired ) BeginInvoke( (MethodInvoker) NotifyDone );
    else {
        // Perform any post-processing work
        MessageBox.Show("Done", "Info");  
    }
}

, ( ThreadProc).

private 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);  
        }  
        NotifyDone();
    }  

, , , , , , . , .

+4

Invoke , , . , Invoke .

, , Invoke . Thread.Sleep - , , .Invoke.

, , , .Invoke. , , .

+1

, , Thread.Sleep(0). , , , , , . , , , , . .

, Thread.Sleep(1) N , N 0,25-1,0 .

, , , ThreadProc.

(0)

Thread.Sleep

Thread.Sleep .

+1

You may also have problems accessing the grid at the same time from different threads. DataTables are not thread safe, so I would suggest that a DataGridView is not. Here is the sample code from this article about DataRow and Concurrency , where you would use Monitor.Enter and Montori.Exit to get some concurrency in place.

    public void DoWorkUpdatingRow(object state)
    {
        List<DataRow> rowsToWorkOn = (List<DataRow>)state;
        foreach (DataRow dr in rowsToWorkOn)
        {
            Monitor.Enter(this);
            try
            {
                dr["value"] = dr["id"] + " new value";
            }
            finally
            {
                Monitor.Exit(this);
            }
        }
    }
+1
source

All Articles