Click here to Skip to main content
15,900,906 members
Articles / Desktop Programming / WPF
Tip/Trick

Update data to WPF control from another thread

Rate me:
Please Sign up or sign in to vote.
4.11/5 (5 votes)
10 Jul 2016CPOL2 min read 33.1K   539   4   5
Update WPF control from another thread apart from UI thread

Introduction

WPF is a powerful tool for developing desktop applications. While developing apps using WPF, many times a situation comes to update UI thread from another background thread or some other thread. This tip explains how to update WPF thread from another thread in a safe way.

Background

I hope you are at least aware of the basics of threading concepts. If not, then no worries. I wil explain here some of the basics.

"Thread is the mother of any process". Remember always, first thread comes and then it takes the shape of process. All threads won't become processes. However, each process must have thread. A process once come in live, i.e., when process is running in OS environment, then it has the capability to request for more OS threads just to delegate tasks and make its own life easy.

Now consider this process is WPF application running on OS. Each process has a thread associated with it, so does with WPF application which we call it as main thread, i.e., Dispatcher thread. All messaging, updating controls, commands, etc. will be taken care of through this main thread (Dispatcher thread). If we try to update any control apart from this main thread, WPF actively refuses and hence we get an exception saying, "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.".

There is access check making another thread fault for UI control update.

So what is the solution for this situation? It's simple, borrow UI thread context and update control through this context from any thread. Remember, we borrowed UI thread context so update will be done through UI thread only even call from another thread to do so.

Let's see first what is a problematic situation with example and then modify the code making the situation better.

Using the Code

Following is a sample code which updates listbox UI control from viewmodel in another thread apart from dispatcher thread:

C#
private void BeginWork()
{
    //time taking job
    //running in another thread
    Task.Factory.StartNew(() => 
    {
        IsWorkDone = false;
        var random = new Random();
        for (int number = 1; number < 100; number++ )
        {
            Numbers.Add(random.Next(100)); //This is where we get thread exception
            Thread.Sleep(1000);
        }
        IsWorkDone = true;
    });
}

Here, Numbers is an observable collection. This collection we want to update at runtime in another thread. As observable collection is binded to ListBox as collection source, we can't update data from another thread. To correct this problem, we will use UI's view context.

Using View Context

View context is nothing but thread synchronization context from main thread. This can be obtained from SynchronizationContext.Current under System.Threading. Following is the modified code using view context:

C#
private void BeginWork()
{
    Numbers.Clear();

    //time taking job
    //running in another thread
    Task.Factory.StartNew(() =>
    {
        IsWorkDone = false;
        var random = new Random();
        for (int number = 0; number < 5; number++)
        {
            ViewContext.Send(x => Numbers.Add
              (random.Next(100)), null); //now this is updating using main ui thread context
            Thread.Sleep(1000);
        }
        ViewContext.Send(x => { NumberSelected = Numbers[0]; IsWorkDone = true; }, null);
    });
}

In ViewModel, we keep a ViewContext property of type SynchronizationContext. In code behind, we assign value for this property like:

Quote:

((MainWindowViewModel)DataContext).ViewContext = SynchronizationContext.Current;

Points of Interest

This is the most simplest and safest way to update in UI thread context.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Synerzip
India India
Passionate about .Net programming.
Having 10+years experience in .Net framework.
Loved working on WPF, WCF, Xamarin, MVVM, Prism
Web development using ASP, ASP.Net, MVC, Angular.JS, Knockout, JQuery, AJAX

Comments and Discussions

 
QuestionYou missed the boat... Pin
PureNsanity11-Jul-16 4:32
professionalPureNsanity11-Jul-16 4:32 
A process requires at least one thread, yes, but that doesn't qualify threads as the mother of a process. A process can contain and spawn multiple threads, so it's really the process that's more of the mother in the relationship.

WPF comes out of the box with two threads - the dispatcher and the renderer. The concept that the dispatcher thread is the "main thread" is a bit misleading. Neither one of these threads is meant for non-UI work either so it's understood the bulk of actual business logic in an application will be done on other threads. If you want to call any encapsulation of threads as a "main" you could argue it's the default ApplicationDomain, IMHO; however, since you can have multiple ApplicationDomains the concept of a "main" is still misleading.

Your solution is a particular setup for joining to the dispatcher thread to execute code, so it's misleading to say you're updating from a different thread. You do seem to understand this, but for some readers it may be confusing.

You also state that messaging and commands will be executed on the Dispatcher. By default this is a really poor recommendation. Any and all work that is not directly updating a UI component should be done on a different thread. While commands do interact with UI components, it's common to have the command do the bulk of it's work off the Dispatcher. Same with messaging.
AnswerRe: You missed the boat... Pin
Jatin Jibhkate12-Jul-16 1:00
Jatin Jibhkate12-Jul-16 1:00 
GeneralRe: You missed the boat... Pin
PureNsanity12-Jul-16 7:37
professionalPureNsanity12-Jul-16 7:37 
QuestionEasier way Pin
EveryNameIsTakenEvenThisOne10-Jul-16 9:31
professionalEveryNameIsTakenEvenThisOne10-Jul-16 9:31 
AnswerRe: Easier way Pin
Jatin Jibhkate10-Jul-16 18:07
Jatin Jibhkate10-Jul-16 18:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.