How to Use SynchronizationContext to Post Messages

Introduction

While working with UI-based applications, one of the most important things that you need to keep in mind is thread Affinity. It ensures that every control needs to be created in the UI Thread to be ported into the UI, and each of them can only be accessed in the UI thread only. Earlier, Windows Forms applications used the ISynchronizeInvoke interface to invoke code in its own thread. SynchronizationContext is a new threading model that allows you to easily communicate with other threading models to simplify the synchronous and asynchronous operations on it.

What is a Synchronization Context?

SynchronizationContext is a new class introduced recently and is being widely used in the .NET base class library itself (in async CTP, for instance) and provides a new way of implementing the Threading Model for your application. It represents the abstract base class for a model that has two methods, namely Send (which invokes a delegate synchronously) and Post (which invokes a delegate asynchronously). Each of these methods takes a delegate of type SendOrPostCallback and the state object. Each time the SynchronizationContext is created, it associates the current thread to its context, so based on the thread in which the block is executing, "SynchronizationContext.Current" always gets you the object that is created in the current thread.

Remember. The Post actually uses ThreadPool internally to call the callback you pass asynchronously.

Now let's create a class that uses SynchronizationContext.

public class MyCallerType  
{  
    private Thread currentThread;  
    private SynchronizationContext context;  
    public event EventHandler EventCallback;    
    public MyCallerType()  
    {  
        context = SynchronizationContext.Current;  
        context = context ?? new SynchronizationContext();    
        currentThread = new Thread(new ThreadStart(Run));  
        currentThread.Start();  
    }    
    private void CallEventHandler(object state)  
    {  
        EventHandler handler = EventCallback;  
  
        if (handler != null)  
        {  
            handler(this, EventArgs.Empty);  
        }  
    }    
    private void Run()  
    {  
        context.Send(new SendOrPostCallback(this.CallEventHandler), null);  
    }  
    private void RunAsync()  
    {  
        context.Post(new SendOrPostCallback(this.CallEventHandler), null);  
    }  
}

The class MyCallerType actually holds the current SynchronizationContext type itself. So when Run orRunAsync is called, it gets the current thread from its SynchronizationContext (which is held from its object creation) and invokes it.

I hope you enjoyed this article. I will cover a bit more later.

Thank you for reading.


Similar Articles