Question

According to this

If the BackgroundWorker starts another BackgroundWorker from its DoWork handler, then the nested BackgroundWorker doesn’t capture the UI SynchronizationContext

enter image description here

However with .NET 4.0 and especially 4.5 onwards, I have seen a lot of sample codes like this one from here:

public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();

      Shown += async ( s, e ) => { txtResult.Text = await DownloadAsync() + "Done!"; };
   }

   async Task<string> DownloadAsync()
   {
      using ( var wc = new WebClient() )
      {
         var progress = new Progress<DownloadStringTaskAsyncExProgress>();

         progress.ProgressChanged += ( s, e ) =>
            {
               progressBar.Value = e.ProgressPercentage;
               txtResult.Text += e.Text;
            };

         return await wc.DownloadStringTaskAsyncEx(
            @"http://ancillaryasync.nickbutler.net/Murphy.ashx", progress );
      }
   }
}

So it looks like you can nest async call using tasks, and the SynchronizationContext will float down the nested calls. Is this correct?

If so, can someone explain to me how the TAP does this on a very high level.

If not what do I need to do make sure my nested call can post to the UI thread?

Or may be my understanding of the original article is completely wrong? Does creation of a new task picks up the current synchronization context by default? If so how can it ever run on anything other than the original synchronization context unless you explicitly give it a new synchronization context?

Please help me clear the confusion.

Was it helpful?

Solution

First off, the article you referenced is talking about BackgroundWorker and not async. BackgroundWorker still works the same way in .NET 4.5, and still has the limitation around nested calls.

For a description of how async works with SynchronizationContext, you can look at the end of that article or read my intro on async. In short, when an await is encountered, by default it will capture the current SynchronizationContext (or if it's null, the current TaskScheduler), and use that to schedule the continuation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top