When working with frameworks like Silverlight, WPF or Windows Forms you often encounter the need to ensure a piece of code runs on the UI thread. Below, I present a clean way to do this using the SynchronizationContext class.

The ISynchronized interface

The first thing to do is to make a contract for all classes that need to expose this functionality. The ISynchronized interface declares this contract. Basically it only exposes a single property which contains the synchronization context on which the code must be executed.

1:using System.Threading;

2:

3:/// <summary>

4:/// Contract for classes that must be able to execute methods in a certain synchronization context.

5:/// </summary>

6:publicinterface ISynchronized

7: {

8:/// <summary>

9:/// Gets the synchronization context.

10:/// </summary>

11:/// <value>The synchronization context.</value>

12: SynchronizationContext SynchronizationContext

13: {

14: get;

15: }

16: }

The extension method

In order to easily use this I have made an extension method that allows specifying an Action to be executed on the synchronization context.

1:using System;

2:

3:/// <summary>

4:/// This class contains the extension methods for the ISynchronized implementations.

5:/// </summary>

6:publicstaticclass SynchronizedExtensions

7: {

8:/// <summary>

9:/// Executes the supplied action in the instance's SynchronizationContext.

The Synchronized method checks if there is a synchronization context and if it is, it will post a call on the synchronization context. If it doesn’t exist, it will call the action directly.

Sample usage

Suppose we have a method SetText which sets the text in a control on the current Form/User control etc. This method must be called on the UI thread, otherwise an exception is raised by the framework. The following method will do this using the above extension method:

public void MethodThatGetsCalledOnAnArbitraryThread(string text)

{

this.Synchronized(() =>

{

this.SetText(text);

});

}

You can write any code inside the action or just use a delegate for this.