David Rickard's Tech Blog

Thoughts on C#, WPF and programming in general

Using the Dispatcher with MVVM

Using the Dispatcher with MVVM

Rate This
  • Comments 9

When writing an MVVM application, you want to separate from the UI. However you also need to make sure that UI updates happen on the UI thread. Changes made through INotifyPropertyChanged get automatically marshaled to the UI thread, so in most cases you’ll be fine. However, when using INotifyCollectionChanged (such as with an ObservableCollection), these changes are not marshaled to the UI thread.

This means that unless you modify your collection on the UI thread, you’ll get a cross threading error. Thus the problem. We’re in the ViewModel and we don’t have access to the Dispatcher. That’s on a View object. How do we update the collection on the UI thread?

I came up with a small static class to help with this:

public static class DispatchService
{
    public static void Invoke(Action action)
    {
        Dispatcher dispatchObject = Application.Current.Dispatcher;
        if (dispatchObject == null || dispatchObject.CheckAccess())
	{
            action();
        }
        else
        {
            dispatchObject.Invoke(action);
        }
    }
}

When your ViewModel gives the DispatchService actions, it can run them on the correct thread. Which is, in the case of unit tests, always the current thread. A call to the DispatchService may look like this:

DispatchService.Invoke(() =>
{
    this.MyCollection.Add("new value");
});

The use of a simple lambda statement makes it a relatively lightweight way of updating on the correct thread.

  • "In your main window constructor, set the DispatchObject to its Dispatcher."

    Can I do this in XAML? How?

    Thanks!

  • Can I use this for any objects, not just Collections? Is that advisable?

  • I don't think you can do this in XAML.

    And yes, you can use the dispatcher for anything you need to do. It's just most useful when dealing with collections because when settings properties it does the work on the correct thread automatically.

  • Simply solution to an annoying problem, thanks alot!

  • Why not just habitually derive your viewmodel from DispatcherObject and call VerifyAccess( ) in all your public methods and properties?  Dispatcher is simply a threading model, it has no necessary correlation to GUI, and I'd wager people aren't clogging their viewmodels with locks. Or let's just say, I would be very disappointed if they were.

  • Straight to the point!

    I added the code:

     DispatchService.DispatchObject = this.Dispatcher;

    in my App.Xaml.cs class constructor

    and then invoked

    DispatchService.Dispatch

    inside the BackgroundWorker.DoWork method, in order to have the UI updated as a consequence of the methods inside the DoWork code.

    Thanks!

  • Why wouldn't you use

    System.Windows.Application.Current.Dispatcher.Invoke((Action)(() => { MyObservableCollectionList.Add("xxx"); }));

    Using this line you don't need to keep reference to GUI dispatcher in your DispatchService.

  • Good point, Vitaliy. I had actually already updated this in my code; I just had not gotten around to updating the blog post. Done.

  • I don't have App.xaml because my application is using window form. In one window I am loading xaml view. In this case where should I initialize DispatchObject.

Page 1 of 1 (9 items)
Leave a Comment
  • Please add 8 and 6 and type the answer here:
  • Post
Translate This Page
Search
Archive
Archives