You might come across a situation where you need to write a multithreading Windows Application, where multiple threads make updates to the UI.
The main purpose of this chapter is to inform you regarding one important issue you need to take care of.
Create a new Windows Application Project. To the main form, add a textbox, named textBox1. Also add a button named button1. In the event handler for button1 (the Click event handler), add the following code:
Thread t = new Thread(new ThreadStart(foo)); t.Start();
Define the function foo as:
void foo()
{
textBox1.Text = "Hullo";
}
Run the application. Click on the button. If you’re running from within the IDE, in Debug Mode – you’ll see an exception getting thrown – “Cross thread operation not valid”. What does this mean? In .NET 2.0, only the thread that creates a UI control is allowed to update it. In our application, one thread created the textbox control and placed it on the form, but another thread is trying to update it (by modifying its Text property).
So how do we get around this? You need to modify the foo() function as shown below:
void foo()
{
textBox1.Invoke(new new_foo_delegate(new_foo));
}
You also need the code below:
public delegate void new_foo_delegate();
void new_foo()
{
textBox1.Text = "Hullo";
}
I won’t go into what delegates are, since that is outside the scope of this tutorial. I’ll just give a brief explanation of what the above code does. Basically, what we’re doing is, we’re informing the runtime, that we have a function called new_foo(), which we want to run on the same thread as the thread which created the textbox1 control. This is done with the help of the Invoke() function. The Invoke() function takes as parameter a delegate, which is a pointer to the function that will actually update the control; and executes that function in the same thread that created the control. Problem solved!
You need to follow this process whenever you have multiple threads updating the UI. Create a function that does the actual update, create a delegate for it, and then from the place where you want the UI to be updated, call the Invoke() function on the corresponding control.