WPF and Multi-threaded programming design

Background

Today a friend of mine wrote me,

We are finally writing our first production WPF application which is fun. Where do you put your async stuff? Is it in your ViewModels? If so, how do you test them?

I’m currently writing a very complex piece of software for scientific researchers, it allows the non-programming savvy scientific researcher the ability to write their own programs in a highly specialized domain-language that I have created specifically for this purpose. There is a lot of threading going on€¦

Common threading uses

I use multi-threading when the application is starting to initialize suitable sub-components simultaneously (and report progress to the user)


Similarly, during long-running data exports from the database I use threading to report progress to the user via a progress-bar and respond quickly to cancel requests.


The language itself

I also use threading to decouple the very slow data persistence layer from the very performance hungry requirements of the domain-language execution. A running program written in the domain language saves a lot of data, and I don’t want to slow-down the running program waiting for the hard drive to persist it all. So the database layer has its own threads for persisting data.

Even the domain-language itself allows multi-threading, although it is hopefully completely transparent. For example, here is a small snippet of the domain-language written by a scientific researcher (note that I didn’t write this for this post) that is inherently multi-threaded:

define phase FixationPhase
// Take away the food hopper – they need to earn the food
move FoodHopper to down position
// Show the fixation circle on the screen
fixation.colour = #55AA2B
fixation.IsVisible = true

// If the subject clicks the fixation circle then
// we need to move to the next phase
when fixation.ClickCount changes then
goto phase Test1Phase
end when
wait(60min * 24)
end phase

This is multi-threaded in a few ways:

  • First, the WPF GUI and the “codes” (as programs written in this domain-language have come to be called) run on their own threads. This of course helps keeps the IDE responsive and also allows the experimenter to use the IDE and review data while the subject is running through the experiment on a second monitor.
  • But even within the experiment this is multi-threaded. The second last line contains a wait(60min * 24) which obviously needs to wait for 24 hours. But if the subject clicks on the fixation shape, then the when clause needs to run, which in this case means going to a completely different phase of the experiment and cancelling the wait request. As shown in the sample above the domain-language makes this easy (hopefully!), but under the covers there is a fair bit of non-trivial threading and cross-thread communication happening to make all of this work and work very fast.

Logging

I also use the wonderful Gibraltar Hub so that I can analyse application performance; specifically I’m looking for memory leaks and degrading performance over time, but of course if there are errors in the log I want to see those as well. By default Gibraltar sends the log files when the application exits, but I’ve discovered that scientific-researches tend to leave the program running all the time, and they never shut off the computers. This means that the logs can become very large and are very rarely sent. I asked the wonderful folks at Gibraltar (they really are amazing) if there was a better way and there was:

Gibraltar 3.0 will make incremental updates of logs much more efficient, but you can address the long running session issue now. You should call Log.SendSessions or Log.SendSessionsAsync once in a while — maybe on a timer.

Easy enough. My original solution was much more complex than it needed be, using threads and wait handles. But when I re-read their comment just now I realized that the much more elegant approach is to use a timer, just like they suggested.

There are actually three Timer classes in .NET:

System.Timers.Timer – Seems easier to use, but less documentation on which thread will make the call
System.Threading.Timer – More powerful but a little more complex
System.Widnows.Forms.Timer – Obviously not really useful for the WPF programmer

In this case I don’t need the extra power, so I’m using the System.Timers.Timer timer.

In my static constructor:

And then in the class itself declared at the bottom of the file along with all my other data:

The view-model and threading

For all of these examples, NONE of them are in the view-model! Typically if you’re talking about threading in the context of WPF you’re talking about using the Dispatcher to “move” a background thread request to the GUI thread. There’s a very complete MSDN article Build More Responsive Apps With The Dispatcher that discusses how this is typically done (it also discusses a new timer class for WPF, the DispatcherTimer).

In fact, I work hard to avoid dealing with the Dispatcher in my view-model, because if I was to switch to the web, WinForms, or Windows8 stuff the dispatcher logic could be completely different, reducing the overall use of the view-model. My goal with the view-model is to imagine a different delivery mechanism for the application that nevertheless looks and works very similar (perhaps so that users can switch back and forth between the two types of applications more easily). So perhaps a Windows 8 version for tablets; of course I’d like to use the same view-model layer if at all possible. Maybe that’s just dreaming and I’m making a (very small) amount of work for myself but I think it’s still worthwhile to strive for the goal: the worst that has happened to me as a result of this is a very clean view-model layer. πŸ™‚

Domain logic layer collections

One place where I do deal with the dispatcher in the view-model layer is when I’m wrapping observable collections. With .NET 4 the ObservableCollection(Of T) class has been nicely placed in the System.Collections namespace (specifically System.Collections.ObjectModel) and the always present System.dll making it very acceptable to use in the domain logic layer. This is a great help and simplification from .NET 3 and 3.5 where we had to jump through hoops to have the view-model layer notified when a collection changed.

However, the WPF GUI really doesn’t like receiving CollectionChanged events from a background thread, and it usually complains bitterly by throwing an InvalidOperationException exception.

However, to simplify, or rather completely eliminate, the need to deal with the dispatcher on a regular basis I use aspect oriented programming. Specifically, I use the amazing and very well designed PostSharp from SharpCrafters. They actually document two very nice dispatcher aspects that can cause a method to automatically run on the GUI thread or a background worker thread.

So after searching my entire code-base for this attribute I found only two occurrences, one when the domain-logic-layer adds a shape to the screen, and the other when it is removed:

Every other occurrence of the ExeucteOnGuiThread aspect in my solution is in the presentation layer where I have the presentation layer subscribing to an event from something that is documented as possibly raising the event on a background thread (such as the splash-screen progress callback or the data-export progress call-back).

Testing

So how do I test this stuff? Unfortunately, usually I test it manually, which is why I try and keep it to a minimum! Another option is to modify your dispatcher code, as I have done, so that you can control the dispatcher that is used, or tell it not to use a dispatcher at all. This means that in your unit tests you can configure no dispatcher and your unit test is essentially single-threaded. This is useful for GUI tests, but not necessary when testing methods attributed with the execute-on-background-thread aspect. This is because although it’s tricky, it’s not really that hard to test multi-threaded code in the domain logic and database layers. For this reason (and improved reuse of course) this is why I much prefer multi-threaded code to be in a non-GUI related layer.

My customized ExecuteOnGuiThread aspect

Extending the PostSharp aspect is remarkably simple, you just have to get over the increasingly common yet unjustified paranoia of all things static. Most unit test zealots will tell you that using static member variables, especially public ones, make your code less testable. However in this case we’re actually using a public static property to make our code much easier to test.
So, in my ExecuteOnGuiThreadAttribute aspect I declare the following public static property:

In my unit tests I simply don’t bother to set this and then the aspect will run it on the same thread as the rest of the unit test, simplifying the unit test greatly.

However, in my actually application start-up code I simply set this as follows:
ExecuteOnGuiThreadAttribute.ApplicationUiDispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
And then any code with that aspect applied will use the application dispatcher.

Here’s the actual code for the aspect’s OnInvoke() method to make this happen pretty seamlessly:

From then on, most of the time you really don’t have to think about it at all, things just work the way they should. That means that I can be a more productive programmer because I’m thinking about the domain problem and not complex threading issues. Once again, a carefully designed aspect makes us much more productive. πŸ™‚ It also means that my view-model layer has no threading code in it whatsoever.

The Presentation layer and threading

For the data-export progress I cheated a little and by-passed the view-model layer. In my data-export component I defined a generic interface:

My dialog box WPF window actually has two constructors, which is something that a lot of WPF developers seem to forget is possible. The first is your basic default constructor created by Visual Studio when I created the Window, and is used by Visual Studio and Expression Blend:

The second constructor is the one my command uses (in this case, the command is defined in the GUI,
which I don’t mind because this particular common would need to be re-written for a dramatically different
GUI version of the application anyway).
This second constructor expects to be given an instance of an ISessionExporter interface, and the first thing it does is subscribe to the OnExportProgress event

The OnExportProgress method of course has my ExecuteOnGuiThread aspect applied to it, making it then easy to update the progress bar control on the dialog box:

So in this case I’m not using MVVM for my progress bar, but instead I cheated slightly and was done programming
the feature slightly faster.
In this case I believe the choice was the right one, because the data-export code is still highly abstracted by the interface,
and the dialog box is not likely to change so much in the future that I would wish I had a view-model layer.
Additionally, in this case there is very little data-translation that needs to be done,
which also reduced the usefulness of trying to build a view-model to encapsulate the data-export progress.

I hope this helps,

Robert

Leave a Reply

Your email address will not be published. Required fields are marked *