Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Extension Methods to Make Thread Safe WPF Programming Easier

0.00/5 (No votes)
21 Oct 2009 1  
Provides extension methods for making thread safe UI programming easier

Introduction

When writing multi-threaded WPF applications, you must ensure that you don't attempt to access any UI elements from any thread other than the main thread. This can lead to repetitive and untidy looking code. Using extension methods, we will look at a simplified method of providing thread safe UI updating.

Background

Sacha Barber presented a method for thread safe UI updating in his article, Useful WPF Threading Extension Method. This article extends his idea and provides a simpler coding construct.

The Example Application

When you run the example application, you can click on the Start button. This will start a timer that will fire every second. Click Stop to stop the timer. When the Thread Safe Mode CheckBox is checked, the UI Elements in the blue box will update every second. If the Thread Safe Mode checkbox is not checked, an exception will occur. When the timer is not running, you can also click on the Update from UI button. This will update the controls in the blue box regardless of Thread Safe Mode being checked or not because it calls UpdateControls from the UI thread.

Using the Code

Using Sacha's original Extension method, the text for textBox1 would be set like this:

this.InvokeIfRequired(() =>
{
	textBox1.Text = "Hello World";
},
DispatcherPriority.Background);

Using my extension methods, the text for textBox1 would be set like this:

textBox1.SetTextThreadSafe("Hello World");

To get the Text of textBox1 using Sacha's extension method would be:

string s = "";
this.InvokeIfRequired(() =>
{
	s = textBox1.Text = "Hello World";
},
DispatcherPriority.Background);

Setting the Text using my extension methods would be:

string s = textBox1.GetTextThreadSafe();

How Does it Work?

We simply define a Get and Set method for the value we want to get or set. For convenience, I have put these methods in the same static class as the InvokeIfRequired method.

An example Set method:

 public static string SetTextThreadSafe(this TextBox tb)
{
	string s = "";
	InvokeIfRequired(tb, () => { s = tb.Text; }, DispatcherPriority.Background);
	return s;
}

An example Get method:

public static void SetTextThreadSafe(this TextBox tb, string s)
{
	InvokeIfRequired(tb, () => { tb.Text = s; }, DispatcherPriority.Background);
}

An extension method must be contained in a static class. Extension methods must also be declared as static methods. The definition of extension methods looks slightly strange because the first parameter is defined with the keyword this followed by the type that the method extends and then the name to use in the method for the instance. Only the first parameter is defined this way. The rest of them are defined normally.

It is best to try and create these methods for the most general class that has the property you want to use. This will prevent you from having to create similar methods for each control type. An example would be the Visibility property. This is a property of UIElement so it would make sense to create a Set and Get method for UIElement rather than one for RadioButton and another for Label, etc.

Once an extension method is defined, it can be used by any instance of the type defined in the declaration or any type that derives from that type. It can also be called statically.

Questions and Answers

Wouldn't It Be Easier to Just Use the InvokeIfRequired Method?

If you only had to use it once or twice, this may be the case. If you are going to access multiple UI elements multiple times, I think my extension methods are easier.

Do I Have to Write an Extension Method for Every UI Element Property?

Otherwise you will need to use the InvokeIfRequired method each time you access a property of a UI element, so why not wrap it inside an extension method and then you only have to do it once? You can then use your WPFThreadingExtensions class in any applications that need it.

I Don't See a Set or Get Extension Method for the Property I Require?

I have provided a few examples of Get and Set extension methods in the test application so you can use these to help you see how to write your own extension methods.

What Do I Do if I Want to Use a Different DispatcherPriority?

I have used DispatcherPriority.Background in my extensions methods. You could change this, create an extension method that takes the DisplatcherPriority you require as a parameter or use the InvokeIfRequired extension method.

History

  • 20th October, 2009: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here