In this post, I would like to briefly discuss the
System.Windows.Threading.Dispatcher class, and the significant differences between its Silverlight and Desktop CLR implementations. We are going to look at solving two things:
- Consuming the UI’s Dispatcher in Silverlight before a page has been instantiated.
- Allowing for synchronous invocation of delegates on the UI thread.
Recently my good friend Sacha Barber published an article, in the comments of which we briefly touched on a cross threading issue that we have both experienced with the Silverlight Dispatcher class. I thought it was about time that I wrote some of this stuff up. This is the result.
Silverlight Thread Affinity
When working with Silverlight, one has to contend with the usual single threaded apartment model (STA) that is also present when working with WPF or Windows Forms. This means that one must interact with UI components, in particular
DependencyObject derived types, from the thread in which they were created on. Fortunately Silverlight/WPF/Windows Forms includes infrastructure that makes acquiring and invoking calls on the UI thread simpler; specifically the
System.Windows.Threading.Dispatcher, which is a prioritized message loop that handles thread affinity.
There is an excellent article describing the Dispatcher in detail.
Consuming the UI’s Dispatcher
In Silverlight, a Dispatcher becomes associated with the main page during initialization, thereby making it available via the Applications
RootVisual property like so:
We can consume the Dispatcher this way, as long as we do so after the
RootVisual has been defined. But in the case where we would like to consume the Dispatcher from the get-go, it leaves us out in the cold. Fortunately though, the Silverlight Dispatcher instance is also available via the
System.Windows.Deployment.Current.Dispatcher property. This instance is defined when the Application starts, thereby making it possible to commence asynchronous operations before the first page is instantiated.
Synchronous Invocation of Delegates on the UI Thread
The Silverlight Dispatcher is geared for asynchronous operations. As we can see from the following image, unlike the Desktop CLR Dispatcher, the Silverlight Dispatcher class’s
Invoke method overloads have internal visibility.
It has to be said that the Desktop CLR Dispatcher, when compared with the Silverlight version, as with many other classes, has a much richer API. In order to provide a means to synchronously invoke a delegate on the UI thread, we need another approach. The approach I have taken is to utilize the
By using the
Send methods of the
DispatcherSynchronizationContext, we are able to regain the synchronous Invoke capabilities within the Silverlight environment.
I have rolled this up into a set of reusable classes, located in my core Silverlight library, which you can find in the
DanielVaughan.Silverlight project in the Calcium http://www.calciumsdk.net download.
A further advantage of using either a Silverlight or Desktop CLR implementation of the
ISynchronizationContext is that we are able to write CLR agnostic code. That is, code that was written for the Desktop CLR can be easily moved to the Silverlight.
Using the code:
In this post, we have looked at consuming the UI’s Dispatcher in Silverlight as soon as an Application starts. We also saw how it is possible in Silverlight to accomplish synchronous invocation of delegates on the UI thread.
The full source shown in this article is available on the Calcium CodePlex site.