Nov 272009
 

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: public interface 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: public static class SynchronizedExtensions

   7: {

   8:     /// <summary>

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

  10:     /// </summary>

  11:     /// <param name="instance">The synchronized instance.</param>

  12:     /// <param name="synchronizedAction">The synchronized action.</param>

  13:     public static void Synchronized(this ISynchronized instance, Action synchronizedAction)

  14:     {

  15:         if (instance.SynchronizationContext != null)

  16:         {

  17:             instance.SynchronizationContext.Post(CallAction, synchronizedAction);

  18:         }

  19:         else

  20:         {

  21:             synchronizedAction();

  22:         }

  23:     }

  24:

  25:     /// <summary>

  26:     /// Calls the passed action.

  27:     /// </summary>

  28:     /// <param name="state">The state.</param>

  29:     private static void CallAction(object action)

  30:     {

  31:         var actionToExecute = action as Action;

  32:         actionToExecute();

  33:     }

  34: }

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.

Download the full source code here: Synchronized.zip
 Executing actions on the UI thread