了解C#5 async/await中的上下文

Use*_*rol 23 c# multithreading conceptual async-await asp.net-4.5

我是否正确async/await本身与并发/并行无关,只不过是继续传递样式(CPS)实现?真正的线程是通过传递/恢复的SynchronizationContext实例来执行的await

如果这是正确的,我有以下问题SynchronizationContext:
它保证在同一个线程上执行继续.

但是,是否有任何保证线程的上下文信息是持久的?我的意思是Name,CurrentPrincipal,CurrentCulture,CurrentUICulture,等它是否依赖于框架(ASP.NET,WinForms的,WCF,WPF)?

Ste*_*ary 35

我是否正确async/await本身与并发/并行无关,只不过是CPS实现?

好吧,async/ await是使用CPS的重写,所以你的核心理解是正确的.

关于"并发"和"并行",我会说它确实能够实现并发性; 你可以同时启动async所有"在飞行中"的多个操作.这很容易做到Task.WhenAllTask.WhenAny.

而且,即使它async本身并不意味着"多线程",Task.Run也能实现易于async兼容的多线程

真正的线程是由等待传递/恢复的SynchronizationContext实例执行的?

可以这样想:CPS重写创建的延续必须在某个地方运行.捕获的"异步上下文"可用于安排继续.

旁注:捕获的上下文实际上是SynchronizationContext.Current 除非它为空,在这种情况下捕获的上下文是TaskScheduler.Current.

另一个重要的注意事项:上下文的捕获和恢复实际上取决于"awaiter"对象.因此,在默认情况下,如果await一个Task(或任何其他内置awaitable),上下文将被捕获和恢复.但如果你await是结果ConfigureAwait(false),那么就不会捕获上下文.同样,如果你await自己的自定义等待,它将不会捕获上下文(除非你编程).

但是,是否有任何保证线程的上下文信息是持久的?我的意思是Name,CurrentPrincipal,CurrentCulture,CurrentUICulture等.

SynchronizationContext不同于ExecutionContext.一个简单的答案是ExecutionContext始终"流动",所以CurrentPrincipal流程(如果没有,则可能是安全问题,这就是为什么不流动的API ExecutionContext总是以最终结束Unsafe).

在UI应用程序中,文化不会流动,但默认情况下,所有线程都是相同的.Name绝对不会流动,除非你在同一个线程上恢复(例如,使用UI SynchronizationContext).


对于进一步的阅读,我建议从我自己async/ await教程开始,然后是官方async/ await常见问题解答.然后看看Stephen Toub关于ExecutionContextvs. 的博客文章SynchronizationContext.

您可能还会发现我的SynchronizationContext文章很有帮助.

  • 谢谢.Stephen Toub关于ExecutionContext和SynchronizationContext的博文的链接对我非常有帮助. (2认同)
  • 伙计,你太异步了。到处都一样。好的! (2认同)