Jaa


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

  • Anonymous
    May 05, 2006
    The following links to .NET resources have been collated over time with the assistance of colleagues. ...

  • Anonymous
    August 28, 2006
    I ran into an issue this summer while helping some interns port Terrarium to use .Net 3.0 and since...

  • Anonymous
    June 12, 2007
    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?

  • Anonymous
    September 20, 2007
    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

  • Anonymous
    July 29, 2008
    WPF requires STA threading. One of the changes to the threading support that shipped in the .Net Framework

  • Anonymous
    December 03, 2008
    In a recent thread in the ADVANCED-DOTNET mailing list , the topic of multiple threads and WinForms came

  • Anonymous
    December 03, 2008
    In a recent thread in the ADVANCED-DOTNET mailing list , the topic of multiple threads and WinForms came

  • Anonymous
    December 04, 2008
    PingBack from http://blog.bruno.locaweb.com.br/2008/12/04/links-for-2008-12-04/

  • Anonymous
    June 17, 2009
    PingBack from http://pooltoysite.info/story.php?id=9737