Cross Thread Communication in Windows Forms: Part II


In this article we will continue learning about cross thread communication in Windows Forms. In the last Article we saw how we can use the BackgroundWorker class to perform cross thread communication. Today we will see how to do the same using Invoke/BeginInvoke methods of Windows Forms controls.

We will make use of a simple "Thread" class to create threads to perform our processor-intensive work and then marshal the result back to the UI thread.

To begin let us declare a variable:

private Thread m_workThread    = null;

Let us define a method that will simulate a long running task and will be called on a separte thread:

private void InvokeReqMethod(object args)
{
    Thread.Sleep(5000);
    if (richTextBox1.InvokeRequired)
    {
        richTextBox1.BeginInvoke(new InvokeDelegate(InvokeMarshalled), args);
    }
}

As you see in the above method we simulate a long running task by calling Sleep() on the thread that invokes that method, and then we use the InvokeRequired property of the UI control, which determines whether it is safe to access the control from a different thread (as it is not, since UI controls are thread unsafe) this will return true always and want us to marshal the call back to UI thread in order to safely access the UI control.
For that we specify another method "InvokeMarshalled" that will be called by InvokeDelegate and it will also marhsal the call back to the UI thread.

private void InvokeMarshalled(object args)
{
    EnableButtons(true);
    progressBar1.Visible = false;
    richTextBox1.AppendText("Marshalled using " + Convert.ToString(args));
}

Next let us define an event handler for the InvokeMarshal button click handler:

private void btnInvoke_Click(object sender, EventArgs e)
{
    EnableButtons(false);
    progressBar1.Visible = true;
    m_workThread = new Thread(new ParameterizedThreadStart(InvokeReqMethod));
    m_workThread.Start("Invoke");
}

Let us verify our implementation, again I set a break point in InvokeReqMethod method and another in InvokeMarshalled method respectively:

CTCWinFor1.gif

Now hit F5 and press InvokeMarshal button on UI, once the debugger is hit:

CTCWinFor2.gif

Once the debug point is hit, you can check in the Threads window again that the current position indicates that the process is in a thread different from the main UI thread.

Next hit F5 and let execution proceed to the method that is called with InvokeDelegate:

CTCWinFor3.gif

The current cursor position now indicates that after BeginInvoke() was called, the method is marshaled back and is being processed on the UI thread. So we have now seen another way to perform cross thread communication in Windows Forms.