System.InvalidOperationException'

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

This post was most recently updated on October 4th, 2022.

2 min read.

If you’re developing something like a WPF app and you 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 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.

Welp – that’s not good. The object’s properties are completely unmodifiable. So how can we update the UI from a background thread in WPF using just C#?

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:

Example where background thread tries to access an object owned by the UI thread – in WPF, this is forbidden!
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 in the example below:

Dispatcher.Invoke example
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 exercise some caution while using it, or you might end up with an unresponsive GUI process!

In some cases, you may want to use BeginInvoke() instead – see below for an example:

Dispatcher.BeginInvoke example
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)
{
    Dispatcher.BeginInvoke((Action) (() =>
    {
        lst_Status.Items.Add(text);
    }));
}

Any further questions? Check out the sources below or leave a comment!

Check these resources out:

mm
5 10 votes
Article Rating
Subscribe
Notify of
guest

1 Comment
most voted
newest oldest
Inline Feedbacks
View all comments