Control.Invoke method not returning

I'm trying to parallelize my code to make it run faster. So far, it's been all headaches and no results.

I want to update several DataGridViews at the same time :

    Parallel.Invoke(
        () => updateDgv1(),
        () => updateDgv2(),
        () => updateDgv3()
    );

I have tried using the easy (but probably not optimal) way recommended everywhere on the web (like here http://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx ).

private void updateDgv1() {
    /* some stuff */

    assignValue(this.dgv1, colPos, rowPos, value); /* in a loop */
    }

    delegate void AssigneValueCallback(DataGridView dgv, int columnPos, int rowPos, string valeur);

    public void assignValue(DataGridView dgv, Form form, int columnPos, int rowPos, string value)
    {
        if (dgv.InvokeRequired)
        {
            AssigneValueCallbackd = new AssigneValueCallback(assignValue);
            dgv.Invoke(d, new object[] { dgv, columnPos, rowPos, value });
        }
        else
        {
            dgv[columnPos, rowPos].Value = value;
        }
    }

The main thread gets stuck at "Parallel.Invoke(...)" call, waiting for the other threads to finish.

The threads created by "Parallel.Invoke(...)" get stuck at this point:

  • mscorlib.dll!System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
  • mscorlib.dll!System.Threading.WaitHandle.WaitOne(int millisecondsTimeout, bool exitContext)
  • System.Windows.Forms.dll!System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle waitHandle)
  • System.Windows.Forms.dll!System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control caller, System.Delegate method, object[] args, bool synchronous)
  • System.Windows.Forms.dll!System.Windows.Forms.Control.Invoke(System.Delegate method, object[] args)
  • etc

Why are they stuck?

Jon Skeet
people
quotationmark

I assume you're calling Parallel.Invoke from the UI thread. If so, that's the problem.

Parallel.Invoke blocks until all the calls finish... which means you're blocking the UI thread. The tasks you're starting can't complete, because Control.Invoke blocks until the call on the UI thread has finished - so your subtasks are waiting for the UI thread to become available in order to update the UI, but your UI thread is waiting for all the subtasks to finish.

You could just fix this by using BeginInvoke instead of Invoke (and you may want to do that anyway) but it's fundamentally a bad idea to use Parallel.Invoke in a UI thread, precisely because it blocks.

people

See more on this question at Stackoverflow