.Net GUI thread crossing

By | 2011.02.25
In this article I thought I’d try to explain the exception: Cross-thread operation not valid: Control ‘someControl’ accessed from a thread other than the thread it was created on. This article is a simplification and applies to WinForm and WPF (though samples are for WinForm).

What is the GUI thread?

When an application starts the main thread is called the GUI thread. This thread is responsible for creating and manipulating GUI. This means any change you make anywhere in your application that will touch any GUI-object needs to be done using the GUI thread.
The GUI thread has the following tasks:
  • Update the GUI.
    Make changes in GUI objects like changing Text in a TextBox.
  • Read Windows Message Queue.
    The WMQ is where Windows put all messages to the application like key clicked, mouse clicked, mouse moved, etc.
  • Repaint the GUI.
    Taking the application from “code” to “graphics”.

As you can see from this, if you tie the GUI thread up in any blocking operation or loop then it will not be able to read WMQ (causing Windows to report application as “Not responding” and app won’t respond to any user interaction) and it will not repaint itself (app seems frozen even if you keep updating GUI objects).

The solution?

Timers

Instead of using a closed loop to update something, use a Timer GUI object (found in Toolbox). It is of type System.Windows.Forms.Timer. This will cause the GUI thread to execute your code at certain intervals.

Do(nt)Events

This approach is just plain-out stupid, wrong and did I mention stupid? You can use Application.DoEvents to force WMQ processing and to repaint the application. This is generally considered a very bad practice because it opens up a whole can of problems.

Invoking GUI thread

All GUI objects know what GUI thread they belong to. You can check with them if they need to be invoked, and if so ask them to invoke. Basically what you are doing then is to ask the GUI thread to execute a method. Note that your thread will not wait for GUI thread to finish.
I made a thread safe class that inherits Form which I posted in an earlier blog post. The essence is something like this:

private delegate void GUIInvokeMethodDelegate(Action @delegate);
/// <summary>
/// Invoke command with GUI thread. Usage: GUIInvoke(() => FormOrControl.Cmd()); 
/// </summary>
/// <param name="delegate">Command to execute in form: () => Cmd()</param>
public void GUIInvokeMethod(Action @delegate)
{
    // Check if we need to invoke as GUI thread    
    if (this.InvokeRequired)
    {
        this.Invoke(new GUIInvokeMethodDelegate(GUIInvokeMethod), @delegate);
        return;
    }    // Execute   
    @delegate.Invoke();
}

// Sample method for invoking some code as GUI-thread
public void DoThisAsGUI()
{
    // Invoke some code (anonymous method)
    GUIInvokeMethod(() =>
    {
        // Something you want to do in GUI thread. 
    });

    // Alternatively invoke a method:
    GUIInvokeMethod(() => SomeMethodThatRequiresGUIThread());
}
The main point here is that before doing any modification to the GUI we check .InvokeRequired. This tells us if we are on the wrong thread, in which case we .Invoke the GUI-thread to do our bidding. By using a wrapper like this it is much easier to invoke the GUI thread.
FacebookLinkedInTwitterOrkutDiggShare/Bookmark

Leave a Reply

Your email address will not be published. Required fields are marked *