System.InvalidOperationException'

Using Dispatcher to update values in GUI elements from a background thread

Quick tip:
If you’re developing something like a WPF app and you’ll need to update values on the User Interface based on a long-running operation that runs in a background thread (like depicted in my other blog post right here – that post is for a full-trust SharePoint solution, but the basic principle is the same!), you’ll probably need to use Dispatcher, or otherwise you’ll run into issues with the GUI elements being owned by another thread, and therefore forbidding access to them. This can result in an error like this:

An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll
 
Additional information: The calling thread cannot access this object because a different thread owns it.

Luckily, there’s a quick workaround available. Read on!

Cue the Dispatcher

MSDN documentation states, that in WPF, only the thread that created a DispatcherObject may access that object. For example, a background thread that is spun off from the main UI thread cannot update the contents of a Button that was created on the UI thread. In order for the background thread to access the Content property of the Button, the background thread must delegate the work to the Dispatcher associated with the UI thread.

That’s cool and all, but how does it work in practice?

This is the pattern I’ve found to work best in this case. Consider the following code:

private void button_OK_Click(object sender, RoutedEventArgs e)
{
       Thread thread = new Thread(delegate ()
       {
             lst_Status.Items.Add("Test");
       });
       thread.IsBackground = true;
       thread.Start();
}

That will not work. You’ll get the aforementioned exception.

Now, if we modify it to use Dispatcher, it’ll look like this:

private void button_OK_Click(object sender, RoutedEventArgs e)
{
       Thread thread = new Thread(delegate ()
       {
            AddMessage("Test");
       });
       thread.IsBackground = true;
       thread.Start();
}
 
public void AddMessage(string text)
{
       this.Dispatcher.Invoke(() =>
       {
            lst_Status.Items.Add(text);
       });
}

You are not allowed to edit the values in GUI elements directly, since you’d be modifying objects that are owned by another thread! Using a pattern like this, you’ll achieve the same effect, and using very straightforward and clean code!

Dispatcher allows you to run your code in the GUI thread’s context, and this is pretty awesome. Using it you can very painlessly update the text values or item collections on GUI elements.

Caveats

It’s worth mentioning, that Dispatcher.Invoke() is a synchronous call, and will block your thread from running until it’s complete. Hence, you might want to excercise some caution while using it, or you might end up with an unresponsive GUI process! You may want to use BeginInvoke() instead – but you need to figure this out yourself!

Check these resources out:

  • http://stackoverflow.com/questions/19968253/does-dispatcher-invoke-block-on-the-calling-thread
  • http://stackoverflow.com/questions/8527778/dispatcher-invoke-from-a-new-thread-is-locking-my-ui
  • MSDN documentation
The following two tabs change content below.

Antti K. Koskela

Solutions Architect / Escalations Engineer at Koskila / Norppandalotti Software / Valo Solutions
Antti Koskela is a proud digital native nomadic millenial full stack developer (is that enough funny buzzwords? That's definitely enough funny buzzwords!), who works as a Solutions Architect for Valo Intranet, the product that will make you fall in love with your intranet. Working with the global partner network, he's responsible for the success of Valo deployments happening all around the world. He's been a developer from 2004 (starting with PHP and Java), and he's been bending and twisting SharePoint into different shapes since MOSS. Nowadays he's not only working on SharePoint, but also on .NET projects, Azure, Office 365 and a lot of other stuff. This is his personal professional (e.g. professional, but definitely personal) blog.

Let me know your thoughts!