“Dispatcher” in WPF

The Dispatcher class is used to perform work on his attached thread. It has a queue of work items and it is in charge of executing the work items on the dispatcher thread.
So, when you want to change a property of a WPF element from a thread different from the one who created the element, you should use the element’s Dispatcher property to dispatch the operation to the correct thread. This is done using the BeginInvoke method that accepts a method to be invoked.
Consider the following program

  1. xaml

1:  <Window x:Class=”DispatcherTrial.MainWindow”

 

10:       <Button Name=”MyButton” Content=”Click Here” Click=”MyButton_Click”></Button>

11:          <TextBlock Grid.Row=”1″ Name=”myText”></TextBlock>

 

13:  </Window>

MainWindow.xaml.cs

private void MyButton_Click(object sender, RoutedEventArgs e)
{
Thread myThread = new Thread(DisplayTime);
myThread.Start();
}

private void DisplayTime()
{
myText.Text = DateTime.Now.ToString();
}
In the click of event of button, I have initialized a new thread. Assigned to that thread is method called “DisplayTime”. Inside “DisplayTime” method, I am assigning the current time to the textblock control. All in all , I am trying to update the UI from code which is running on a separate thread. Ideally the code should run fine but it doesn’t. It throws an exception of type :- InvalidOperationException. And following is the error message : The calling thread cannot access this object because a different thread owns it. Our WPF applications run on STA model. The thread the controls the application is commonly known as UIThread. “Dispatcher” concept is a mechanism introduced in WPF , with the help of which developer can have more explicit control on this UI thread as of what executes when.
Just keep these in mind before going in details.
• Thread that creates a given WPF application also own it and its not possible for any other thread to interact with these elements.
• In practice entire WPF application runs of single thread and its this thread that owns all the elements in the application.
• Dispatcher Concept
As the name implies, the dispatching system is responsible for listening to various kinds of messages and making sure that any object that needs to be notified of that message is notified on the UI thread.
The classes responsible for “Dispatcher” concept are : DispatcherObject and Dispatcher. Actually its the “Dispatcher” class which provides the core implementation of dispatching mechanism. But its the “DispatcherObject” class which exposes a public property called “Dispatcher” , through which we can access the current instance of “Dispatcher” class. Have a look at the following class hierarchy diagram :

every single entity in WPF derives from the “DispatcherObject” class. Following is the internal implementation of “DispatcherObject” class.
“DispatcherObject” class offers a public accessor property called “Dispatcher” using which we can access the current instance of “Dispatcher” class. As the WPF application runs , Dispatcher class accepts incoming requests and executes them one at a time. In short dispatcher is an object which receives messages and delivers it to the correct object for further processing. One final thing on dispatcher class is that a given application can have only one instance of dispatcher class( as the application runs on single thread) i.e. Singleton. Because of that its impossible to create an instance of Dispatcher class in our custom code. Only with the help of public property “Dispatcher” offered by “DispatcherObject” that we can invoke members defined inside the “Dispatcher” class. Dispatcher class is instantiated as soon as any class which derives from “DispatcherObject” is accessed. All further request are processed by this newly created instance.
Dispatcher class is instantiated as soon as any class which derives from “DispatcherObject” is accessed. All further request are processed by this newly created instance.

Coming back to “DispatcherObject” class , it offers two methods namely CheckAccess and VerifyAccess.

CheckAccess : Determines whether the calling thread has access to this DispatcherObject. Only possible return values are true and false.
VerifyAccess : VerifyAccess is more stringent compared to CheckAccess. It checks whether the calling thread is the one which created the DispatcherObject. If not it throws “InvalidOperationAccess” exception. Getting back to the example which I gave in the beginning, in that we were trying to update the UI through code which was running on a different thread. Internally VerifyAcess is invoked and once it verifies that calling code is different from the one which controls the application, it throws the “InvalidOperationError” exception.

Dispatcher maintains an internal queue of work items and it process each work items one after the other. Each work item in the queue is has its associated priority. Items are executed relatively to each other on the basis of their priority values.

private void MyButton_Click(object sender, RoutedEventArgs e)
{
this.Dispatcher.BeginInvoke(new Action(this.DisplayTime), DispatcherPriority.Background);
}
private void DisplayTime()
{
myText.Text = DateTime.Now.ToString();
}
Most often priority value “Background” is used for application specific custom logic.
”BeginInvoke” is a member exposed by the “Dispatcher” class. BeginInvoke adds the delegate to the Dispatcher’s event queue but gives you the opportunity to specify a lower priority for it. This ensures that the Dispatcher processes all loading and rendering events before executing the delegate that loads the data. This allows the control or window to be displayed and rendered immediately, whilst the data waits in the background to be loaded.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s