ConfigureAwait(true)不返回它等待的上下文

时间:2015-08-16 17:41:54

标签: c# multithreading asynchronous async-await

示例:

 static void Main(string[] args)
 {
     int counter = 0;
     var t = new System.Timers.Timer();
     t.Interval = 3000;
     t.Elapsed += async (sender, e) =>  
     {
        Debug.WriteLine("Before await - Thread : {0} , Counter : {1}", Thread.CurrentThread.ManagedThreadId, counter);
        await Task.Delay(1000).ConfigureAwait(true);
        Debug.WriteLine("Ater await Thread : {0}, Counter : {1} ", Thread.CurrentThread.ManagedThreadId, counter);

         counter++;
         if (counter == 2)
         {
            Debug.WriteLine("Stop");
            t.Stop();
         }
     };

     t.Start();

     Console.ReadKey();
 }   

这总是输出:

 Before await - Thread : 4 , Counter : 0 
 Ater await Thread : 4, Counter : 0  
 Before await - Thread : 5 , Counter : 1 
 Ater await Thread : 4, Counter : 1  

 Stop 

为什么它没有返回线程await被调用。它第一次执行,但随后计时器在线程5上运行,并且假设捕获异步操作结束时的上下文,并且您可以看到它在线程4上返回。

2 个答案:

答案 0 :(得分:4)

控制台应用中没有任何同步上下文。

如果您在WinForms中运行代码,并且您发现它可以按预期运行..

答案 1 :(得分:4)

  

为什么它没有在线程上返回await被调用。

await在相同的上下文上恢复,而不是相同的线程。有时这些是相同的 - 特别是在UI应用程序中,UI上下文绑定到特定的UI线程。其他时候没有相关性 - 例如,ASP.NET有一个请求上下文,它不依赖于特定的线程。在这种情况下,Console应用程序正在使用线程池上下文,因此该方法将在线程池线程上恢复。

  

有没有办法将后台线程与同步上下文相关联?

这是一项非常罕见的要求。通常情况下,开发人员只需认为他们就需要这个。我的第一个建议是从任何需要它的代码中删除特定的线程要求,例如,用更现代的解决方案替换ThreadStatic

但是,如果您真的必须使用具有同步上下文的后台线程,那么您可以使用AsyncContext.Run from my AsyncEx library