April 2014

Volume 29 Number 4


MVVM : Multithreading and Dispatching in MVVM Applications

Laurent Bugnion

Just about a year ago I began a series of articles on the Model-View-ViewModel (MVVM) pattern for the MSDN Magazine Web site (you can access them all at is.gd/mvvmmsdn). The articles show how to use the components of the MVVM Light Toolkit to build loosely coupled applications according to this pattern. I explore the dependency injection (DI) and inversion of control (IOC) container patterns (including the MVVM Light SimpleIoc), introduce the Messenger and discuss View services (such as Navigation, Dialog and so forth). I also show how to create design time data to maximize the use of visual designers such as Blend, and I talk about the RelayCommand and EventToCommand components that replace event handlers for a more decoupled relationship between the View and its ViewModel.

In this article, I want to delve into another frequent scenario in modern client applications—handling multiple threads and helping them communicate with each other. Multithreading is an increas­ingly important topic in modern application frameworks such as Windows 8, Windows Phone, Windows Presentation Foundation (WPF), Silverlight and more. On every one of these platforms, even the least powerful, it’s necessary to start background threads and to manage them. In fact, you could argue that it’s even more important on small platforms with less computing power, in order to offer an enhanced UX.

The Windows Phone platform is a good example. In the very first version (Windows Phone 7), it was quite difficult to get smooth scrolling in long lists, especially when the item templates contained images. However, in later versions the decoding of images, as well as some animations, are passed to a dedicated background thread. As a result, when an image is loaded, it doesn’t impact the main thread anymore, and the scrolling remains smooth.

This example underlines some important concepts I’ll explore in this article. I’ll start by reviewing how multithreading works in XAML-based applications in general.

Simply put, a thread can be considered as a smaller unit of execution of an application. Each application owns at least one thread, which is called the main thread. This is the thread that gets started by the OS when the main method of the application is called, on startup. Note that more or less the same scenario happens on all supported platforms, as much on WPF running on powerful computers as on Windows Phone-based devices with limited computing power.

When a method is called, the operation is added to a queue. Each operation is executed sequentially, according to the order in which it was added to the queue (though it’s possible to influence the order in which the operations are executed by assigning a priority to them.). The object responsible for managing the queue is called the thread’s dispatcher. This object is an instance of the Dispatcher class in WPF, Silverlight and Windows Phone. In Windows 8, the dispatcher object is named CoreDispatcher and uses a slightly different API.

As required by the application, new threads can be started explicitly in code, implicitly by some libraries or by the OS. Mostly, the purpose of starting a new thread is to execute an operation (or wait on the result of an operation) without blocking the rest of the application. This can be the case of a computationally intensive operation, an I/O operation and so on. This is why modern applications are increasingly multithreaded, because UX requirements are also increasing. As applications become more complex, the number of threads they start increases. A good example of this trend is the Windows Runtime framework used in Windows Store apps. In these modern client applications, asynchronous operations (operations running on background threads) are very common. For instance, every file access in Windows 8 is now an asynchronous operation. Here’s how a file gets read (synchronously) in WPF:

public string ReadFile(FileInfo file)
{
  using (var reader = new StreamReader(file.FullName))
  {
    return reader.ReadToEnd();
  }
}

And here’s the equivalent (asynchronous) operation in Windows 8:

public async Task<string> ReadFile(IStorageFile file)
{
  var content = await FileIO.ReadTextAsync(file);
  return content;
}

Note the presence of the await and async keywords in the Windows 8 version. They’re there to avoid using callbacks in asynchronous operations, and to make the code easier to read. They’re needed here because the file operation is asynchronous. The WPF version, in contrast, is synchronous, which risks blocking the main thread if the file that’s getting read is long. This can cause choppy animations, or a lack of update on the UI, which worsens the UX.

Similarly, long operations in your applications should be taken care of on a background thread if they risk making the UI choppy. For example, in WPF, Silverlight and Windows Phone, the code in Figure 1 initiates a background operation that runs a long loop. In every loop, the thread is put to sleep for a short time to give time to the other threads to process their own operations.

Figure 1 Asynchronous Operation in the Microsoft .NET Framework

public void DoSomethingAsynchronous()
{
  var loopIndex = 0;
  ThreadPool.QueueUserWorkItem(
    o =>
    {
      // This is a background operation!
      while (_condition)
      {
        // Do something
        // ...
        // Sleep for a while
        Thread.Sleep(500);
      }
  });
}

Letting Threads Communicate

When a thread needs to communicate with another thread, some precautions need to be taken. For example, I’ll modify the code in Figure 1 to display a status message to the user on each loop. To do this, I just add a line of code in the while loop, which sets the Text property of a StatusTextBlock control located in the XAML:

while (_condition)
{
  // Do something
  // Notify user
  StatusTextBlock.Text = 
    string.Format("Loop # {0}", loopIndex++);
  // Sleep for a while
  Thread.Sleep(500);
}

The application named SimpleMultiThreading that accompanies this article shows this example. If you run the application using the button labeled “Start (crashes the app),” the application, indeed, crashes. So what happened? When an object is created, it belongs to the thread on which the constructor method was called. For UI elements, objects are created by the XAML parser when the XAML document is loaded. This all happens on the main thread. As a consequence, all the UI elements belong to the main thread, which is also often called the UI thread. When the background thread in the previous code attempts to modify the Text property of the StatusTextBlock, this creates an illegal cross-thread access. As a consequence, an exception is thrown. This can be shown by running the code in a debugger. Figure 2 shows the exception dialog. Notice the “Additional information” message, which indicates the root of the problem.

Cross-Thread Exception Dialog
Figure 2 Cross-Thread Exception Dialog

In order for this code to work, the background thread needs to queue the operation on the main thread by contacting its dispatcher. Thankfully, each FrameworkElement is also a DispatcherObject as shown by the .NET class hierarchy in Figure 3. Every DispatcherObject exposes a Dispatcher property that gives access to its owner dispatcher. Thus, the code can be modified as shown in Figure 4.

Window Class Hierarchy
Figure 3 Window Class Hierarchy

Figure 4 Dispatching the Call to the UI Thread

while (_condition)
{
  // Do something
  Dispatcher.BeginInvoke(
    (Action)(() =>
    {
      // Notify user
      StatusTextBlock.Text = 
        string.Format("Loop # {0}", loopIndex++);
    }));
  // Sleep for a while
  Thread.Sleep(500);
}

Dispatching in MVVM Applications

When the background operation is executed from a ViewModel, things are a little different. Typically, ViewModels don’t inherit from DispatcherObject. They’re plain old CLR objects (POCOs) that implement the INotifyPropertyChanged interface. For example, Figure 5 shows a ViewModel deriving from the MVVM Light ViewModelBase class. In true MVVM manner, I add an observable property named Status that raises the PropertyChanged event. Then, from the background thread code, I attempt to set this property with an information message.

Figure 5 Updating a Bound Property in the ViewModel

public class MainViewModel : ViewModelBase
{
  public const string StatusPropertyName = "Status";
  private bool _condition = true;
  private RelayCommand _startSuccessCommand;
  private string _status;
  public RelayCommand StartSuccessCommand
  {
    get
    {
      return _startSuccessCommand
        ?? (_startSuccessCommand = new RelayCommand(
          () =>
          {
            var loopIndex = 0;
            ThreadPool.QueueUserWorkItem(
              o =>
              {
                // This is a background operation!
                while (_condition)
                {
                  // Do something
                  DispatcherHelper.CheckBeginInvokeOnUI(
                    () =>
                    {
                      // Dispatch back to the main thread
                      Status = string.Format("Loop # {0}", 
                         loopIndex++);
                    });
                  // Sleep for a while
                  Thread.Sleep(500);
                }
              });
          }));
    }
  }
  public string Status
  {
    get
    {
      return _status;
    }
    set
    {
      Set(StatusPropertyName, ref _status, value);
    }
  }
}

Running this code in Windows Phone or Silverlight works fine until I try to data bind the Status property to a TextBlock in the XAML front end. Running the operation again crashes the application. Just like before, as soon as the background thread attempts to access an element belonging to another thread, the exception is thrown. This occurs even if the access is done through data binding.

Note that in WPF, things are different and the code shown in Figure 5 works even if the Status property is data-bound to a TextBlock. This is because WPF automatically dispatches the PropertyChanged event to the main thread, unlike all the other XAML frameworks. In all other frameworks, a dispatching solution is needed. In fact, what’s really needed is a system that dispatches the call only if necessary. In order to share the ViewModel code between WPF and other frameworks, it would be great if you didn’t have to care about the need to dispatch, but had an object that would do this automatically.

Because the ViewModel is a POCO, it doesn’t have access to a Dispatcher property, so I need another way to access the main thread and to enqueue an operation. This is the purpose of the MVVM Light DispatcherHelper component. In essence, what this class does is store the main thread’s Dispatcher in a static property and expose a few utility methods to access it in a convenient and consistent manner. In order to be functional, the class needs to be initialized on the main thread. Ideally, this should be done early in the application’s lifetime, so the features are accessible from the application’s start. Typically, in an MVVM Light application, the DispatcherHelper is initialized in App.xaml.cs, which is the file defining the startup class of the application. In Windows Phone, you call Dispatcher­Helper.Initialize in the InitializePhoneApplication method, right after the application’s main frame is created. In WPF, the class is initialized in the App constructor. In Windows 8, you call the Initialize method in OnLaunched, right after the windows is activated.

After the call to the DispatcherHelper.Initialize method is complete, the UIDispatcher property of the DispatcherHelper class contains a reference to the main thread’s dispatcher. It’s relatively rare to use the property directly, but it is possible if needed. Instead, however, it’s better to use the CheckBeginInvokeOnUi method. This method takes a delegate as parameter. Typically, you use a lambda expression as shown in Figure 6, but it could also be a named method.

Figure 6 Using DispatcherHelper to Avoid Crashing

while (_condition)
{
  // Do something
  DispatcherHelper.CheckBeginInvokeOnUI(
    () =>
    {
      // Dispatch back to the main thread
      Status = string.Format("Loop # {0}", loopIndex++);
    });
  // Sleep for a while
  Thread.Sleep(500);
}

As the name suggests, this method performs a check first. If the caller of the method is already running on the main thread, no dispatching is necessary. In that case, the delegate is executed immediately, directly on the main thread. If, however, the caller is on a background thread, the dispatching is executed.

Because the method checks before dispatching, the caller can rely on the fact the code will always use the optimal call. This is especially useful when you’re writing cross-platform code, where multithreading might work with small differences on different platforms. In that case, the ViewModel code shown in Figure 6 can be shared anyway, without any need to modify the line where the Status property is set.

In addition, DispatcherHelper abstracts the differences in the dispatcher API between the XAML platforms. In Windows 8, the CoreDispatcher’s main members are the RunAsync method and the HasThreadAccess property. In other XAML frameworks, however, the BeginInvoke and CheckAccess methods are used, respectively. By using the DispatcherHelper, you don’t have to worry about these differences, and can more easily share the code.

Real-Life Dispatching: Sensors

I’ll illustrate the use of DispatcherHelper by building a Compass sensor Windows Phone application.

The sample code accompanying this article contains a draft application named CompassSample - Start. When you open this application in Visual Studio, the access from the MainViewModel to the compass sensor is encapsulated in a service called SensorService, which is an implementation of the ISensorService interface. These two elements can be found in the Model folder.

The MainViewModel gets a reference to the ISensorService in its constructor and registers for every compass change using the SensorService RegisterForHeading method. This method requires a callback, which will be executed every time the sensor reports a change in the Windows Phone-based device heading. In the MainViewModel, replace the default constructor with the following code:

sensorService.RegisterForHeading(
  heading =>
  {
    Heading = string.Format("{0:N1}°", heading);
    Debug.WriteLine(Heading);
  });

Unfortunately, there’s no way to simulate the device compass in the Windows Phone emulator. To test the code, you’ll need to run the app on a physical device. Connect a developer device and run the code in debug mode by clicking F5. Observe the Output console in Visual Studio. You’ll see the output of the Compass listed. If you move the device, you’ll be able to find the north and observe how the value keeps updating.

Next, I’ll bind a TextBlock in XAML to the Heading property in the MainViewModel. Open the MainPage.xaml and locate the TextBlock located in the ContentPanel. Replace the “Nothing yet” in the Text property with “{Binding Heading}”. If you run the application again, in debug mode, you’ll witness a crash with an error message similar to the earlier one. Again, this is a cross-thread exception.

The error is thrown because the compass sensor runs on a background thread. When the callback code is called, it also runs on the background thread, as does the setter of the Heading property. Because the TextBlock belongs to the main thread, the exception is thrown. Here, too, you need to create a “safe zone” to take care of dispatching the operations to the main thread. To do this, open the SensorService class. The CurrentValueChanged event is handled by a method named CompassCurrentValueChanged; this is where the callback method is executed. Replace this code with the following, which uses DispatcherHelper:

void CompassCurrentValueChanged(
  object sender,
  SensorReadingEventArgs<CompassReading> e)
{
  if (_orientationCallback != null)
  {
    DispatcherHelper.CheckBeginInvokeOnUI(
      () => _orientationCallback(e.SensorReading.TrueHeading));
  }
}

Now the DispatcherHelper must be initialized. To do this, open App.xaml.cs and locate the method called InitializePhoneApplication. At the very end of this method, add DispatcherHelper.Initialize();. Running the code now produces the expected result, displaying the Windows Phone-based device heading properly.

Note that not all sensors in Windows Phone raise their events on a background thread. The GeoCoordinateWatcher sensor, for instance, which is used to observe the phone’s geolocation, already returns on the main thread for your convenience. By using DispatcherHelper, you don’t have to worry about this and can always call the main thread’s callback in the same manner.

Wrapping Up

I discussed how the Microsoft .NET Framework handles threads and what precautions need to be taken when a background thread wants to modify an object created by the main thread (also called the UI thread). You saw how this can cause a crash, and that to avoid this crash, the main thread’s Dispatcher should be used to properly handle the operation.

Then I translated this knowledge to an MVVM application and introduced the DispatcherHelper component of the MVVM Light Toolkit. I showed how you can use this component to avoid issues when communicating from a background thread, and how it optimizes this access and abstracts the differences between WPF and the other XAML-based frameworks. By doing so, it allows easy sharing of ViewModel code and makes your work easier.

Finally, I demonstrated in a real-life example how the Dispatcher­Helper can be used in a Windows Phone application to avoid issues when you’re working with certain sensors that raise their events on a background thread.

In the next article, I’ll delve further into the Messenger component of MVVM Light, and show how it can be used for easy communication among objects without any need for them to know about each other, in a true decoupled manner.


Laurent Bugnion is senior director for IdentityMine Inc., a Microsoft partner working with technologies such as Windows Presentation Foundation, Silverlight, Pixelsense, Kinect, Windows 8, Windows Phone and UX. He’s based in Zurich, Switzerland. He is also a Microsoft MVP and a Microsoft Regional Director.

Thanks to the following technical expert for reviewing this article: Thomas Petchel (Microsoft)