1. |
Add the System.Threading namespace:
|
2. |
For each method on the main UI you want to invoke, create a delegate with the appropriate signature, e.g. if all we want to do is pass back a string status to the main UI thread for display, then create a delegate with a single string parameter:
delegate void StringParameterDelegate(string value); |
3. |
To start your worker thread without parameters:
Thread t = new Thread(new ThreadStart(ThreadJob)); t.IsBackground = true; t.Start(); To start your worker thread with parameters use the ParameterizedThreadStart delegate instead, and pass all your args as a single object (so compact multiple args into a single object - array, struct etc):
Thread t = new Thread(new ParameterizedThreadStart(ThreadJob)); t.IsBackground = true; t.Start("Some Arg"); |
4. |
Create your UI method to update some control on the form, and have it run under two modes - called from the worker thread and called from the UI thread:
void UpdateFormElement(string value) { if (InvokeRequired) { BeginInvoke(new StringParameterDelegate(UpdateFormElement), new object[]{value}); return; } myFormLabel.Text = value; }The way this works is InvokeRequired checks if the calling thread is the same as the one the method exists in - if it's different (InvokeRequired) then the delegate is invoked instead, this then calls the same method, but this time from the UI thread, which is thread-safe. The InvokeRequired if block is passed, and the actual UI element can be updated with the value. This allows the same UpdateFormElement method to be called from any thread and it will work. |
5. |
All you need to do now is call the UpdateFormElement from the worker thread:
void ThreadJob() // takes one arg of type object if ParameterizedThreadStart was used { // cast it into the object/primitive you originally called it with |
And that is all there is! Your worker thread can now invoke the same function as the UI thread to update the UI controls! |