Using the Dispatcher with MVVM

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.