Multi-threading in WPF part II: Code Sample
In the first part of this post series I briefly explains WPF threading concept and options you have to enable asynchronous operation in your application. On this post, I’ll show you the techniques you can use.
In my earlier blog post, I’ve created a WPF application that connects to MSN Live Search service. If you run the application you will find it hangs for a few seconds after Search() method is called. The first search request will take a while before the response comes back. During that time, the application becomes unresponsive. My attempt here is to execute this long-running search operation asynchronously on separate thread.
Using Dispatcher (the wrong way)

Using Dispatcher the wrong way
As you can see from the code, what I’m doing here is simply create a new thread with some UI updating logic attached as delegate. Now after I call Start() method on the new thread, SendSearchRequestWrong method will be executed. Things will go fine until the search result is returned. The thread will try to update UI in ClearCurrentDisplayResultmethod.
This code is destined to fail because it breaks the thread affinity as I mentioned in part I. This new thread won’t be able to find the UI thread since it’s executing in a different context. The exception will be raised and its error message says it all: “The calling thread cannot access this object because a different thread owns it“. Nuff’ said.

Using Dispatcher (the right way)
Now let’s see how to get this to work.

Using Dispatcher the right way
The key to make it work here is wrapping the UI update logic inside a delegate and execute it with Dispatcher.BeginInvoke method. This will make sure that the code is executing on the right context. You can also specify the DispatcherPriority level as well. It’s recommended to give UI update code Normal priority and save other higher priorities for a more critical execution.
When you run the sample code, you’ll see that application interface is responsive during the searching. You will be able to type in the search query text box. This is because the long running operation is moved from the main UI thread to another thread.

The search result
BackgroundWorker
The BackgroundWorker class was introduced in .NET 2.0. Using BackgroundWorker ensures that the long running task is executed on a separate thread. BackgroundWorker uses Dispatcher and events while abstracts away marshaling issues, leaving you with the asynchronous goodness.
The other neat thing is that BackgroundWorker also supports two events: progress changed and cancellation. Both events provide a way for long running thread to interact with the UI. You also do not have to worry about execution context, it’s all taken care of for you.
Creating BackgroundWorker
The normal way is you create BackgroundWorker instance in the code and configure the events. You can also declare the BackgroundWorker in XAML file. I prefer the latter. By doing so, you can use attributes to wire the event handlers.
First, you will have to import System.ComponentModel namespace to the XAML. Next, declare an instance of BackgroundWoker in Windows.Resources section of the XAML. Since BackgroundWorker is not a UI element, you have to declare it as a resource.

Declaring BackgroundWoker in XAML
As you can see, declaring BackgroundWorker in XAML allows you to declare event handlers for RunWorkerCompleted, DoWork, and ProgressChanged events right in the markup.
Using the BackgroundWorker
In the code, you can access and use the declared BackgroundWorker instance by
- Add application logic to event handlers for this
BackgroundWoker - Calling
FindResource("<instance name>")method to access the instance - Call
RunWorkAsyncmethod to start execution

Retrieving declared BackgroundWorker instance

Declaring BackgroundWorker event handlers
Once the BackgroundWoker is fired, DoWork method will be called. RunWorkerCompleted event is called when execution is finished. Meanwhile, if you declare WorkReportProgress attribute to be true, you can use ReportProgress(double) to update the UI. When ReportProgress method is called, BackgroundWorker.ProgressChanged event will be fired.
Note that I call BackgroundWorker.ReportProgress method inside DoWork. Since this MSN Live search API calls cannot really be broken down to percentage completed, I will simply assign 10% completion when request input is retrieved, 20% when the search is initiated, and 70% when the search result is returned.

Fire BackgroundWorker by calling RunWorkerAsyncMethod
Finally, when the code runs, you can see that the percentage completion is reported and display back in the interface. This is because I update the completion percentage text block every time ProgressChanged event is fired.

Updating UI for completion percentage
The completion percentage report text block is hidden when the result is ready and rendered to the UI.

Last word
So, from this blog post series you can see that multi-threading in WPF is not difficult to achieve. Keep in mind that although it’s a lot like multi-threading in WinForm, but you have to be aware of some WPF-specific threading issues. IMHO, using BackgroundWorker can help you achieve this quite easily. Otherwise, you can go direct to use Dispatcher or threading as well.
You can download the code sample HERE
Teera on February 22nd 2008 in Software Development, WPF, .NET













