Introduction

In my previous article, Silverlight Cairngorm, I provided the essential Cairngorm constructs in Silverlight, like the abstract ModelLocator, FrontController, CairngormDelegate, and CairngormEventDispatcher, etc. Since it is ported from Flex ActionScript, and Flex doesn't support multi-threaded programming directly, it has no considerations on threading related issues. If the RIA you're planning follows a similar programming model as Flex does, not creating a worker thread or a thread-pool thread to perform background process, then using the previous version of the Silverlight Cairngorm is sufficient, you don't need to worry about threading and synchronizations.

However, if your Silverlight application is multi-threaded, it would require the framework --- Silverlight Cairngorm to be thread-safe. Specially, ModelLocator singleton creation and access needs to be thread safe, and all data binding event dispatching in the base abstract classes needs to be raised on the correct thread, or an exception will be thrown, or a wrong object reference created. This article details the improvements made on the previous version of the Silverlight Cairngorm in order to make it thread-safe, and also provides an updated demo project that uses a thread-pool thread to perform data transformations and data binding updates.

Thread-safe Singletons in the Silverlight Cairngorm

Within the Silverlight Cairngorm framework, CairngormEventDispatcher is an internal singleton object. Although it's not accessible by the application code, it's still important to be thread-safe in order to make sure the dispatched CairngormEvent is correctly routed to the associated command. Here is the common not-thread-safe singleton code for CairngormEventDispatcher:

namespace SilverlightCairngorm.Control
{
///<summary>/// Used to dispatch system events, by raising an event that the
/// controller class subscribes to every time any system event is
/// raised.
/// Client code has no need to use this class. (internal class)
///</summary>internalclass CairngormEventDispatcher
{
privatestatic CairngormEventDispatcher instance;
///<summary>/// Returns the single instance of the dispatcher
///</summary>///<returns>single instance of the dispatcher</returns>publicstatic CairngormEventDispatcher getInstance()
{
if ( instance == null )
instance = new CairngormEventDispatcher();
return instance;
}
///<summary>/// private constructor
///</summary>private CairngormEventDispatcher()
{
}
//...Other code omitted to focus on singleton
}
}

In a multi-threaded application, different threads could run at line if ( instance == null ) and evaluate it to be true, then multiple instances could be created in getInstance(); the direct impact would be some CairngormEvent is dispatched, but the corresponding command is not executed. Here is the thread-safe while not-using-lock implementation:

//Thread-safe singleton implementation that not using lock
namespace SilverlightCairngorm.Control
{
///<summary>/// Used to dispatch system events, by raising an event that the
/// controller class subscribes to every time any system event is
/// raised.
/// Client code has no need to use this class. (internal class)
///</summary>internalclass CairngormEventDispatcher
{
privatestaticreadonly CairngormEventDispatcher _instance =
new CairngormEventDispatcher();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static CairngormEventDispatcher()
{
}
///<summary>/// private constructor
///</summary>private CairngormEventDispatcher()
{
}
/// Returns the single instance of the dispatcher
publicstatic CairngormEventDispatcher
Instance { get { return _instance; } }
//...other code omitted to focus on singleton
}
}

The static constructor is to help the C# compiler to ensure laziness of the type initializer to create the private static field of _instance correctly and only once; static constructors in C# are specified to execute only when the class is instantiated or a static member is referenced, and to execute only once per AppDomain.

Usually, in a Silverlight Cairngorm application, like in the demo project, the application's ModelLocator and FrontController are derived from the base abstract class, and are implemented as singletons. The above simple approach can be easily applied to those derived classes in the application. All the code changes for those two singletons are included in the demo project download.

Initializing an Event Delegate with an Empty Anonymous Method

Again, in the internal class CairngormEventDispatcher, the EventDispatched event is implemented in a way that requires the dispatchEvent method to check whether the delegate is null (to see if there is any event listener) before invoking it; here is the previous code:

Juval Lowy in his book Programming .NET Components, Second Edition offered a nice trick to hook up an empty anonymous method to the delegate in its declaration; then, we never have to check for null before invoking the delegate, since there will always be one no-op subscriber in its subscriber list. It can also avoid a potential race condition when un-subscribing in a multi-threaded application. Here is the updated code for EventDispatchDelegate:

Similarly, the ModelLocator uses the same approach to make the code simpler and safer; details are in the source code.

Thread-safe Data Binding Events

The ModelLocator is meant to be the DataContext (you can certainly have other data as DataContext) to the application for data binding, that's why the abstract base class implements the INotifyPropertyChange interface. It works well (even for the update collection data as shown in the demo project, each search result updates a collection of FlickRPhoto objects) in a single threaded application. Since Silverlight has the same rule regarding updating the UI (needs to perform on the same thread that creates the UI element) as WPF or Windows Forms does, it's important to make the INotifyPropertyChange implementation to be thread-safe for a multi-threaded application, or a Model is updated from a different thread other than the UI thread, and the PropertyChanged event is raised in a non-UI thread, Silverlight will throw an UnauthorizedAccessException exception (WPF will throw an InvalidOperationException exception for the same reason).

The idea to make the PropertyChanged event thread-safe in Silverlight is to check the executing thread is the UI thread before invoking the event delegates; if it's on the same thread, invoke it directly; if not, dispatch it to the correct thread, then the UI (data binding) updates without an exception.

Here is the thread-safe version of the ModelLocator's INotifyPropertyChange implementation:

The body of the abstract ModelLocator is almost empty, it is the base type, BindableBase, makes sure that the derived ModelLocator type will have to implement the INotifyPropertyChange interface and also the implementation is thread-safe:

Another reason to separate out the BindableBase type is to make it reusable for other potential model data types. For example, if the application has a view needs to data bind to its own View Model, rather than the ModelLocator, the View Model type can derive from BindableBase, it would get the same benefits of thread-safety from BindableBase.

The initialization of the UI thread's dispatcher is deferred till the very first NotitifyPropertyChange event raised, the protected CheckDispatcher method will retrieve the dispatcher from RootVisual to make sure it's actually referencing the UI thread's dispatcher. This deferred instantiation enables the ModelLocator can be instantiated before RootVisual is loaded.

Thread-safe ObservableCollection Wrapper

When dealing with dynamic data collection as DataContext for data binding in a multi-threaded application, we also need to make the INotifyCollectionChanged event to be dispatched on the UI thread as well. In Silverlight Cairngorm v0.0.1.3, the new type, BindableCollection, wraps ObservableCollection and derives from BindableBase to make both the INotifyCollectionChange and INotifyPropertyChange implementation thread-safe:

In BindableCollection, while making data binding events thread-safe, it also implements all public methods that ObservableCollection exposes via 8 interfaces. All implementation details can be found at the downloadable source code.

Test Out Thread-safety

All of the above are the changes in the Silverlight Cairngorm to make it thread-safe; now, let's update our demo project to test it out. The major change in the demo project is in the SearchPhotoCommand's onResult method. The new ProcessResultFromThreadPool method will parse the FlickR API returning XML, transform it to a collection of FlickRPhoto objects, then notify data binding to populate new data; all this happens in a thread-pool thread (non-UI thread). Here is the code:

You can put a break point at the line currentDispatcher.BeginInvoke(new Action <string>(NotifyPropertyChanged), propertyName); in the ModelLocator base class to see how it works. Then, comment out ProcessResultFromThreadPool(resultStr); from onResult, and un-comment out ProcessResult(resultStr); (to make it run in the same thread) to see how it behaves.

History

Updated Silverlight Cairngorm FrontController ---- each registered Cairngorm Event will be handled by a new instance of corresponding Cairngorm Command, this will make Silverlight Cairngorm FrontController work in the same way as Flex's Cairngorm 2.2.1's FrontController.

Also updated demo project to reflect the new addCommand signature to pass in the type of Command, rather than the instance of Command.