TAP中的SynchronizationContext默认行为(任务异步模式)

时间:2013-09-13 00:53:53

标签: c# asynchronous task-parallel-library desktop-application synchronizationcontext

根据this

  

如果BackgroundWorker从其中启动另一个BackgroundWorker   DoWork处理程序,然后嵌套的BackgroundWorker不捕获   UI SynchronizationContext

enter image description here

然而,对于.NET 4.0,尤其是4.5以后,我在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 );
      }
   }
}

因此看起来您可以使用任务嵌套异步调用,并且SynchronizationContext将向下浮动嵌套调用。这是对的吗?

如果是这样,有人可以向我解释TAP如何在非常高的水平上做到这一点。

如果不是我需要做什么,请确保我的嵌套调用可以发布到UI线程?

或者可能是我对原文的理解是完全错误的?默认情况下,创建新任务是否会获取当前同步上下文?如果是这样的话除非你明确地给它一个新的同步上下文,它怎么能在除原始同步上下文之外的任何东西上运行?

请帮我澄清一下这个混乱。

1 个答案:

答案 0 :(得分:4)

首先,您引用的文章是BackgroundWorker而不是asyncBackgroundWorker在.NET 4.5中仍然以相同的方式运行,并且仍然存在嵌套调用的限制。

有关async如何与SynchronizationContext一起使用的说明,您可以查看该文章的结尾或阅读我的intro on async。简而言之,当遇到await时,默认情况下它会捕获当前SynchronizationContext(或者如果它是null,当前TaskScheduler),并使用它来安排延续。