C# Threading: Windows Forms and WPF InvokeRequired / CheckAccess

October 26, 2010 by C#   Threading  

When interacting with UI via threads (using Windows Forms) you might have seen the following exception:
Cross-thread operation not valid: Control 'x' accessed from a thread other than the thread it was created on.

A Simple way to reproduce this exception, is to simply create a Windows Forms app, drop a button on the form, attach an event handler on the click event (of the button) and create a thread that attempts to access the button, for example:

private void action()
{
    button1.Text = "Clicked";
}

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(action);
    t.Start();
}

The reason behind this exception is because Windows Form controls aren't thread safe, so in order to achieve some kind of thread safety, the UI controls are bound to the thread it was created on and in order to access them, one needs to reside in the same thread.

How does one achieve this (reside in the same thread) exactly?

One way, is to check the InvokeRequired property on the control and use the Invoke (synchronous) or BeginInvoke (asynchronous) method on the control in order to send some code (via delegate) to the thread that owns it, observe:

private void action()
{
    if (button1.InvokeRequired)
    {
        button1.Invoke(new Action(action));
        return;
    }
    button1.Text = "Clicked";
}

If we try to do the same thing (access controls that reside in the UI thread) in a WPF Application, we are confronted with the same issues,
private void action()
{
    button1.Content = "Clicked";
}

private void button1_Click(object sender, RoutedEventArgs e)
{
    Thread t = new Thread(action);
    t.Start();
}

The exception message looks a little bit different though:
The calling thread cannot access this object because a different thread owns it.

And unlike the Windows Forms solution, you won't find the InvokeRequired property on the WPF controls, instead one can use the Dispatcher property, observe:

private void action()
{
    if (button1.Dispatcher.CheckAccess())
    {
        button1.Content = "Clicked";
        return;
    }
    button1.Dispatcher.Invoke(
        System.Windows.Threading.DispatcherPriority.Normal,
        new Action(action));
}

Something interesting to note, is that CheckAccess method (and a few overloads within the invoke method) is hidden to intellisense, which is achieved by the following attribute:
[EditorBrowsable(EditorBrowsableState.Never)]

Looking at other solutions, you might want to have a look at the AsyncOperationManager & SynchronizationContext classes - perhaps a future post.


Leave a Comment


Senior Principal Engineer November 7, 2017 by Andrew

Awesome explanation, nothing like it - anywhere. Well done!

great May 27, 2014 by Anonymous

Your explanation is the best i met on the internet ! Note if one use a filesystemwatcher to monitor file or folder, it is launched in a new thread, thus you need too use invoke or dispatcher.

Alexander December 8, 2010 by Anonymous

Thank you very much for your post about Windows Forms and WPF InvokeRequired / CheckAccess. I found it at the moment when I was about to give up and it helped me to move and complete my work.