Using SynchronizationContexts.


SynchronizationContext is new in .NET 2.0, and I haven’t found too much written about it yet.  It is used by classes like BackgroundWorker and some other built-in classes, and I wanted to show how you can use it in your code as well.  I came across this while working on my WinCast project where I needed to handle events coming from the RSS synchronization engine on a background thread.  I wanted to handle these events (like a new feed added) by adding new UI elements.  If you’ve done any work in Windows programming, you are probably aware that accessing the UI from a thread that didn’t create the UI is a big no no.  In .NET 1.1, we could use Invoke on a control to get something executed on the UI thread, but that wasn’t the greatest solution.  .NET 2.0 brings us SynchoronizationContext which allows us to execute a section of code in the UI context (the thread that created the UI).  Also, it allows us to specify if the background thread will block waiting for the UI thread (using Send) or will not block (using Post).  You can get the UI context from the WindowsFormsSynchronizationContext.Current property.  Here is an admittedly dumb example of a lastUpdatedTime being updated on a background thread, and the UI being properly updated on the UI thread to show the new time in a textbox.


public partial class UsingContextForm : Form
{
   
SynchronizationContext uiContext;
   
System.Timers.Timer backgroundTimer;
   
DateTime lastUpdated = DateTime.Now;


   public UsingContextForm()
   
{
      
// save our ui context for use later
      
uiContext = WindowsFormsSynchronizationContext.Current;

      
InitializeComponent();
   
      
// start a timer on a background thread 
      
backgroundTimer = new System.Timers.Timer(1000.0);
      
backgroundTimer.Elapsed += new System.Timers.ElapsedEventHandler(backgroundTimer_Elapsed);
      
backgroundTimer.Start();
   
}


   void backgroundTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
   
{
      
//This executes on a background thread
      
lastUpdated = DateTime.Now;

      
//Tell the ui thread to execute some code for us.
      
uiContext.Send(new SendOrPostCallback
            
delegate(object state) 
            
{
               
//This executes on the ui thread
               
textBox1.Text = lastUpdated.ToLongTimeString();
            

         
), null);
   
}
}

Comments (9)

  1. The following links to .NET resources have been collated over time with the assistance of colleagues. …

  2. Hoop Somuah says:

    I ran into an issue this summer while helping some interns port Terrarium to use .Net 3.0 and since…

  3. From your example, I don’t see what the advantage is of using a SynchronizationContext instead of just using BeginInvoke().

    We now have two mechanisms to accomplish basically the same thing. What can be done with a SynchronizationContext that couldn’t be done using the ISynchronizeInvoke interface?

  4. Dave Comer says:

    Matt,

    Although the post is old, and there still is very little written on the subject, I found your blog helpful. For others that are seeking similar help, here is a link to a Codeproject article that does a good job discussing the SynchronizationContext use.

    http://www.codeproject.com/cs/threads/SyncContextTutorial.asp?print=true

  5. WPF DotNet says:

    WPF requires STA threading. One of the changes to the threading support that shipped in the .Net Framework

  6. In a recent thread in the ADVANCED-DOTNET mailing list , the topic of multiple threads and WinForms came

  7. In a recent thread in the ADVANCED-DOTNET mailing list , the topic of multiple threads and WinForms came