【问题标题】:ConfigureAwait(true) not returning on the context it was awaited onConfigureAwait(true) 没有返回它等待的上下文
【发布时间】:2015-08-16 17:41:53
【问题描述】:

示例:

 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 

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

【问题讨论】:

  • 即使在控制台应用程序中也能正常工作
  • @msmolcic 可能碰巧让 if 停在 6 点或其他地方,看看它是否仍然如此

标签: c# multithreading asynchronous async-await


【解决方案1】:

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

如果您在 WinForms 中运行您的代码,您会发现它会按预期工作..

【讨论】:

  • 有没有办法可以将后台线程与同步上下文相关联?我真的不想每次调用都返回调用它的同一个线程。
  • @eranotzap 您可以在代码开头添加Form1 form = new Form1();,例如
【解决方案2】:

为什么它没有返回线程等待被调用。

await 在相同的上下文中恢复,而不是相同的线程。有时它们是相同的——尤其是在 UI 应用程序中,UI 上下文与特定的 UI 线程相关联。其他时候没有相关性——例如 ASP.NET 有一个请求上下文,它不绑定到特定线程。在这种情况下,控制台应用程序正在使用线程池上下文,因此该方法在线程池线程上恢复。

有没有一种方法可以将后台线程与同步上下文相关联?

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

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

【讨论】:

    猜你喜欢
    • 2020-05-11
    • 1970-01-01
    • 2017-10-29
    • 2015-11-19
    • 2019-02-20
    • 2023-03-08
    • 1970-01-01
    • 2019-02-25
    • 2013-09-29
    相关资源
    最近更新 更多