Follow Us

Skip Navigation LinksHome > Articles > WPF > How to Create multithreaded UI application in WPF

How to Create multithreaded UI application in WPF

Explains various ways to create the multi threaded UI application in WPF

By Pankaj   On   Monday, 22 September 2008

Page Views : 80499   |   Technologies : WPF

Rating : Rated :
5
| More..

WPF Multithreading

Sometime application has to perform long-running tasks. In a typical application, tasks are processed synchronously. When one task completes, the next begins execution, and this continues in a sequential fashion.

 

So, what would happen to the UI while waiting for a long-running task to finish? Often the UI becomes unresponsive and may even freeze temporarily until a long-running task completes.

This is referred to as blocking on a thread. e.g., executing a large batch process against a database in response to user interaction could render an application unresponsive until the database operation completes. Therefore, thread execution is essentially blocked until the process completes.

 

When an application has to perform a long-running task, one solution to the problem of synchronous thread blocking is to create a separate background thread and allow it to run asynchronously. Running threads in parallel frees the application to accept more input from the user and start other tasks. The background thread can then alert the application when it completes, allowing the application to respond as appropriate—a process known as thread synchronization. Multithreading has been around for quite a while and works the same in WPF as it did in Windows Forms. Only the implementation details and underlying support are different, and that’s what we will discuss in this article.

 

In this article, we will look at ways to schedule long-running processes in your WPF applications so that they run asynchronously rather than synchronously in order to create a responsive UI. We’ll also look at how you can synchronize multiple threads so that your UI can get updated when an asynchronous process returns. We will look at the following:

 

  • Single-threaded application model
  • Thread affinity and DispatcherObject
  • WPF dispatcher
  • Synchronous threading
  • Asynchronous threading
  • Background Worker object

 

Single-Threaded Application Model

WPF objects belong to the thread on which they are created and cannot be accessed by any other thread directly. When an object is tied to a single thread, it is said to be a single-threaded object. This means that you cannot directly modify UI objects from any thread other than the thread on which you create them. For example, a background thread cannot update the contents of a TextBox control that was created on an application’s main UI thread. Of course, WPF supports a model for accomplishing this, but it is well defined to ensure thread safety.

 

In COM development, this threading model is called the Single Threaded Apartment (STA) model. Windows Forms also uses this same model. What is different about the WPF implementation is the extent to which this model is enforced and the way it is enforced through the use of the DispatcherObject.

 

You might have probably noticed that in both WPF and Windows Forms applications the Main() application entry point is decorated with a [STAThread] attribute.

 

[STAThread]

static void Main()

{

}

The [STAThread] attribute defines the application as using a single-threaded apartment model.

More specifically, it changes the state of the application thread to be single-threaded.

 

Thread Affinity:

Thread affinity means that the some objects cannot be accessed directly from the other thread than it was created with. It means, an object with thread affinity can be accessed only on the thread that has created it.

 

DispatcherObject:

How is thread affinity enforced by WPF? The rule of thumb is that any objects derive from DispatcherObject, they become objects that exhibit thread affinity. WPF objects that participate in the threading model derive, directly or indirectly, from DispatcherObject. This includes objects such as Application, Visual, and DependencyObject. At first glance, this may seem like a small list, but we’re talking about important base classes here, from which most framework classes derive. For instance, because Visual ultimately derives from DispatcherObject, then all UI elements have thread affinity as well.

 

  • DispatcherObject enforces thread affinity and, therefore, thread safety among WPF objects.
  • WPF uses a Dispatcher object to route messages from Windows to your application.
  • One and only one dispatcher is created for the UI thread.
  • Only the thread that created the dispatcher may access a dispatcher object. Messages from Windows, such as input generated on other threads, can only access your application’s UI thread through the dispatcher message loop. This enforces the thread affinity model. 

 

DispatcherObject offers two methods you can use to determine if your object is on the correct thread:

VerifyAccess and CheckAccess. Both methods basically return a Boolean value indicating whether you are on the correct thread. The following code snippet shows how you might use VerifyAccess in a program to ensure an element has access to the current UI thread:

try

{

this.btnLongProcess.VerifyAccess();

MessageBox.Show(“The Button Has Access”);

this.btnLongProcess.Content = “I Belong”;

}

catch (InvalidOperationException e)

{

// Button does not have direct access, need to update through Dispatcher

}

 

 

One thing to notice is that the VerifyAccess method does not return a value. It will, however, throw an InvalidOperationException if access is denied. If access is denied, you need to use the dispatcher of the thread to which the target object belongs to perform an action on the target object. We would see in an example later.

 

WPF Dispatcher:

Applications need a mechanism to respond to user and system input such as mouse clicks, key presses, and system events. In Win32, this mechanism is called a message loop and it’s an integral component of every Windows application. The message loop runs in the background of a Win32 application and routes messages to the application from Windows.

 

For example, when a mouse button is clicked, Windows sends a message to the message loop indicating that the mouse button was indeed clicked, and also, which mouse button was clicked, left or right. Windows places the messages in a prioritized queue for the window that generated the click. The message loop continually monitors this queue and dispatches messages to the application.

 

In WPF, the message loop and queue are created and managed by the dispatcher. A dispatcher is an instance of the Dispatcher class. The dispatcher runs each task, one at a time, based on the task’s priority level. Dispatcher is really a message dispatcher.

 

In its simplest form, an application runs a single UI thread. One or many worker threads may be created, as well, to perform tasks in the background. In order for a worker thread to interact with the main UI thread, it must do so by passing messages to the UI thread’s dispatcher. There is an important rule of thumb to understand about the dispatcher: only the thread that creates the dispatcher may access it. In other words, there is a one-to-one relationship between the dispatcher and the thread that creates it.

 

WPF creates a dispatcher for your main UI thread so you do not have to declare one.

One thread cannot access another thread’s objects directly. If a background thread does attempt to update the UI thread directly, an access violation in the form of an exception is thrown. Dispatcher provides the methods Invoke and BeginInvoke, which a background thread can use to schedule tasks on the UI thread and to specify delegates the dispatcher can use to modify the target object. Messages passed to the dispatcher are marked with a priority level and placed in a queue managed by the dispatcher.

The dispatcher executes messages based on priority (not based on FIFO or LIFO methods).

 

The following table details the different message priority levels in the DispatcherPriority enumeration.

Dispatcher Priority enumeration Description

  • ApplicationIdle: Dispatcher will process when application is idle.
  • Background: Dispatcher will process after all other non-idle operations are complete.
  • ContextIdle: Dispatcher will process when the context is idle.
  • DataBind: Dispatcher will process at the same priority as data binding.
  • Inactive: Dispatcher will not process.
  • Input: Dispatcher will process at the same priority as input.
  • Invalid: Dispatcher will not process.
  • Loaded: Dispatcher will process when firing the Loaded event.
  • Normal: Dispatcher will process normally.

 

Dispatcher Priority Description

  • Render Dispatcher will process at the same priority as rendering.
  • Send Dispatcher will process before other asynchronous operations.
  • SystemIdle Dispatcher will process when the system is idle.

It is important to schedule your tasks on another thread with the correct priority. If you do not schedule correctly, the task may not be executed as expected.

 

Working with Single-Threaded Applications

When you perform long-running tasks synchronously on your UI thread you run the risk of your UI becoming unresponsive. When a method is called that executes a long-running process, your thread of execution waits for the method to return. You will explore using asynchronous multithreading to avoid blocking in the next example, but for now, let’s write a simple example to illustrate how blocking affects our UI’s responsiveness.

 

Let’s create a quick example to see how blocking affects your application. Open Visual Studio and create a new project based on the WPF Windows Application template and name the project WPFThreading.

You’ll be adding a few windows to this application throughout the chapter, so rename the default Window1 to BlockThread. You’ll use the same XAML in all of the examples in this section to illustrate the effects of your code on the UI, so you’ll just display the XAML once. Refer to this XAML if you need to for examples that follow.

 

Modify the default window’s XAML as follows:

<Window x:Class="WPFThreading.BlockThread"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  Title="UI Thread Only" Height="275" Width="225"

  >

 

  <Border Width="200" Height="225" BorderBrush="Black"

    BorderThickness="1" Margin="4">

    <StackPanel>

 

      <Label>Start Long-Running Process</Label>

      <Button Name="btnLongProcess" Click="btnLongProcess_click" Width="108">Go to sleep</Button>

 

      <Label Width="193">Can I respond?</Label>

      <Button Name="button2" Click="button2_click" Width="113">Try Me</Button>

 

      <Label>Output Messages</Label>

      <TextBox Name="textbox1"/>

 

      <Label/>

 

      <StackPanel Orientation="Horizontal">

        <Label>UI thread:</Label>

        <Label Name="UIThreadId"></Label>

      </StackPanel>

 

      <StackPanel Orientation="Horizontal">

        <Label>BG thread:</Label>

        <Label Name="BGThreadId"></Label>

      </StackPanel>

 

    </StackPanel>

  </Border>

</Window>

 

You’re simply defining a couple of buttons, a textbox to receive output messages; a couple of labels to display thread IDs, some additional labels, and a few styles.

Next, modify the code-behind as follows:

public partial class BlockThread : System.Windows.Window

  {

 

    public BlockThread()

    {

      InitializeComponent();

 

      this.UIThreadId.Content = this.Dispatcher.Thread.ManagedThreadId;

      this.BGThreadId.Content = "N/A"; //NO BG thread in this window

    }

 

    private void LongRunningProcess()

    {

      // simulate long running process for 20 seconds

      System.Threading.Thread.Sleep(20000);

      this.textbox1.Text = "Done Processing...";

    }

 

    private void btnLongProcess_click(object sender, RoutedEventArgs e)

    {

      // set up a block on this UI thread

      LongRunningProcess();

    }

 

    private void button2_click(object sender, RoutedEventArgs e)

    {

        //try this while first is process is running

      this.textbox1.Text = "Hello WPF did I response?";

    }

 

  }

 

When you run the application, you are presented with two buttons. Pressing the first button labeled “Start Long Process” will put the thread to sleep for 20 seconds, simulating a long-running process. If you try to click the second button, labeled “Try Me,” during the 20 seconds sleep period, the UI will be unresponsive and the button event will not fire. You see how to get rid of this in the next example.

 

Asynchronous Threading

In a previous example, you put together a window that blocked execution of your UI thread by putting it to sleep for 20 seconds, resulting in a UI that would not respond during long running task. You need to write some code now to handle the simulated long-running process in a manner that will keep your UI responsive. To do this, You’ll process your long-running task asynchronously on a worker thread separate from your UI thread. In order to start the thread asynchronously, you’ll be using .NET delegates. Delegates can also be used to execute functions asynchronously. A delegate in your code provides Invoke and BeginInvoke methods. You can use Invoke to execute a method synchronously, or BeginInvoke to execute a delegate method on a separate thread in the background asynchronously.

Using delegates for asynchronous method execution is not new to WPF. What is new in WPF is how you can synchronize your UI thread when an asynchronous method returns. In WPF, thread synchronization is performed through the Dispatcher object.

Using your previous “WPFThreading” project, create a new Window and name it  to unblockThread.

You’ll use the same window XAML as your previous Blocking example, so you can simply copy from the last example. Let’s modify the code-behind for your new window, as follows:

public partial class UnblockThread : System.Windows.Window

  {

 

    private delegate void SimpleDelegate();

 

    public UnblockThread()

    {

      InitializeComponent();

 

      this.UIThreadId.Content = this.Dispatcher.Thread.ManagedThreadId;

      this.BGThreadId.Content = "N/A";

    }

 

 

      /// <summary>

      /// This method is called in the background worker thread of the thread pool,

      /// so it can not access the UI object directly. we used delegate to update the UI.

      /// </summary>

    private void LongRunningProcess()

    {

      int threadid = Thread.CurrentThread.ManagedThreadId;

 

      // Display this threads id using delegate as you can not access the UI created in main thread

      SimpleDelegate del1 = delegate()

        { this.BGThreadId.Content = threadid; };

      this.Dispatcher.BeginInvoke(DispatcherPriority.Send, del1);

 

      Thread.Sleep(20000);

 

      // Schedule UpdateTextBox with the UI thread's Dispatcher

      SimpleDelegate del2 = delegate()

        {this.textbox1.Text = "Done Long Running Task...";};

      this.Dispatcher.BeginInvoke(DispatcherPriority.Send, del2);

    }

 

    private void btnLongProcess_click(object sender, RoutedEventArgs e)

    {

      // simulate long running process asynchronously

      SimpleDelegate del = new SimpleDelegate(LongRunningProcess);

      del.BeginInvoke(null, null);

    }

 

    private void button2_click(object sender, RoutedEventArgs e)

    {

      this.textbox1.Text = "Hello WPF, I can repsonse any time";

    }

 

  }

 

When you run the application, you achieve the results you want: a responsive UI. Let’s look at the details of how you accomplished this.

First, you declare a couple of namespaces, System.Windows.Threading and System.Threading. You need System.Windows.Threading to be able to schedule your delegate and set its priority with the Dispatcher.

You need System.Threading to get access to the Sleep method for simulating your longrunning process. You also declare a delegate, which takes no arguments to support the operations you’ll perform later. This code is typical delegate boilerplate code.

Next, you modify your LongRunningProcess method. This method is going to be executing in a separate thread this time, so it cannot directly update the BGThreadId or the output message textbox1 target on the UI thread. What you need to do is to schedule the update to BGThreadId and textbox1 with the Dispatcher. To do this, you create a couple of delegate instances using anonymous delegate syntax and schedule them with the Dispatcher using a priority level of DispatcherPriority.Send through a call to BeginInvoke. In this case, BeginInvoke is being executed as a method of the Dispatcher (not the delegate). Dispatcher.BeginInvoke accepts a delegate and will execute the delegate’s BeginInvoke method for you.

Finally, you need to execute your long-running process on a separate thread. To do this, you create a delegate and then call BeginInvoke on the delegate. Don’t confuse calling BeginInvoke on the delegate with BeginInvoke on the Dispatcher. This will run your delegate code in a separate thread.

Note that for simplicity, you are not passing an AsyncCallback argument in your delegate’s call to

BeginInvoke; rather, you are passing null. In a real-world scenario, you would want to specify a callback method so you could call EndInvoke on your delegate to free up system resources.

 

Asynchronous Threading with Background Worker Object

As an alternative to using delegates to spin off worker threads, the BackgroundWorker class also allows you to perform long-running processes in a separate thread. The BackgroundWorker class is not new to WPF, but you can still use it in WPF. BackgroundWorker basically hides the implementation details of multithreading for you and provides some event mechanisms you can use to get messages back from the thread. Using this method, you no longer have to use the Dispatcher to synchronize threads.

 

Let’s rewrite the previous non-blocking example you created, this time using BackgroundWorker. Add a new form to your project, and name it UnblockThreadTwo. Use the same XAML as before.

public partial class UnblockThreadTwo : System.Windows.Window

  {

 

    private BackgroundWorker worker;

 

    private delegate void SimpleDelegate();

 

    public UnblockThreadTwo()

    {

      InitializeComponent();

 

      this.UIThreadId.Content = this.Dispatcher.Thread.ManagedThreadId;

      this.BGThreadId.Content = "N/A";

    }

 

    private void btnLongProcess_click(object sender, RoutedEventArgs e)

    {

      worker = new BackgroundWorker();

 

      worker.DoWork += new DoWorkEventHandler(RunOnBGThread);

 

      worker.RunWorkerCompleted += new

        RunWorkerCompletedEventHandler(BGThreadWorkDone);

 

      worker.RunWorkerAsync();

    }

 

    private void button2_click(object sender, RoutedEventArgs e)

    {

      this.textbox1.Text = "Hello WPF";

    }

 

    private void LongRunningProcess()

    {

      int threadid = Thread.CurrentThread.ManagedThreadId;

 

      // Display this threads id

      SimpleDelegate del1 = delegate()

        { this.BGThreadId.Content = threadid; };

      this.Dispatcher.BeginInvoke(DispatcherPriority.Send, del1);

 

      Thread.Sleep(20000);

    }

 

    private void RunOnBGThread(object sender, DoWorkEventArgs e)

    {

      LongRunningProcess();

    }

 

    private void BGThreadWorkDone(object sender,

      RunWorkerCompletedEventArgs e)

    {

       this.textbox1.Text = "Done Sleeping..";

    }

 

  }

Let’s look at the code. First, you need to declare the System.ComponentModel namespace, which is where the BackgroundWorker class resides, and then define a BackgroundWorker instance.

In the btnLongProcess_click event, you connect some event handlers to handle events raised by the BackgroundWorker instance. BackgroundWorker raises four events: Disposed, DoWork,

ProgressChanged, and RunWorkerCompleted. You are handling two of these events here. The last thing you do in this function is run your BackgroundWorker instance.

Finally, you define your event handler methods. When the thread starts, you receive the DoWork event. In your handler for this event you call your LongRunningProcess method. When the thread finishes, you handle the RunWorkerCompleted event by displaying a status message as before, only this time you are already backing on the UI thread, so no special code is required.

The System.Windows.Threading namespace, delegate, and call to Dispatcher.BeginInvoke are used only to display the background thread ID to stay consistent with the other examples. The longrunning process is managed by the BackgroundWorker instance.

The BackgroundWorker class provides a simple mechanism for creating and managing threads in your applications.

 

Summary: We have seen how a single threaded application becomes unresponsive. We discussed two different ways to make application responsive using the dispatcher and background worker thread in WPF.


Keywords :
Tags :
Rate This Article :

Comments :

# 1 Annonymous Wrote on 09/24/2008


Very useful articles about multithreading in WPF. Thanks.



# 2 Annonymous Wrote on 10/04/2008


Please attach a code sample. Its better than copy paste. The article is nice and useful. Thanks. Keep Smiling :) Yours Pankaj Nikam.



# 3 Pankaj Wrote on 10/04/2008


Please download the source code from the top of the article.



# 4 Annonymous Wrote on 10/04/2008


Oops it was overlooked. Thanks :)



# 5 Annonymous Wrote on 03/29/2009


Very great job. thanks



# 6 Annonymous Wrote on 07/12/2009


Got some concepts clear as a newbie.Thank you.



# 7 Annonymous Wrote on 10/07/2009


Excellent articles



# 8 Annonymous Wrote on 10/19/2009


very nice



# 9 hxibrahim Wrote on 10/05/2010


This is a great post. Thank you so much for writing this detailed article. Indeed it solved so many problems in my project.




blog comments powered by Disqus
User Login
Username :
Password :
Register Login

Forgot Password


Related Articles