Nei*_*ell 57 c# continuations async-await
我一直在考虑C#5中新的异步内容,并提出了一个特别的问题.
我知道await关键字是一个简洁的编译器技巧/语法糖来实现连续传递,其中方法的其余部分被分解为Task对象并排队以按顺序运行,但是控制返回到调用方法.
我的问题是,我听说目前这一切都在一个线程上.这是否意味着这种异步内容实际上只是将连续代码转换为Task对象然后Application.DoEvents()在每个任务完成之后调用,然后再开始下一个任务?
或者我错过了什么?(问题的这一部分是修辞 - 我完全清楚我错过了什么 :))
Ste*_*ary 52
它是并发的,因为许多优秀的异步操作可能在任何时候都在进行中.它可能是也可能不是多线程的.
默认情况下,await将连续计划安排回"当前执行上下文"."当前执行上下文"被定义为SynchronizationContext.Current它是非null,或者TaskScheduler.Current如果没有SynchronizationContext.
您可以通过调用覆盖此默认行为,ConfigureAwait并通过false对continueOnCapturedContext参数.在这种情况下,继续将不会被安排回该执行上下文.这通常意味着它将在线程池线程上运行.
除非您正在编写库代码,否则默认行为正是您所希望的.WinForms,WPF和Silverlight(即所有UI框架)提供了一个SynchronizationContext,因此延续在UI线程上执行(并且可以安全地访问UI对象).ASP.NET还提供了一个SynchronizationContext确保继续在正确的请求上下文中执行的方法.
其他线程(包括线程池线程,Thread和BackgroundWorker)不提供SynchronizationContext.因此,默认情况下,控制台应用程序和Win32服务根本没有SynchronizationContext.在这种情况下,continuation在线程池线程上执行.这就是为什么控制台应用程序演示使用await/ async包括调用Console.ReadLine/ ReadKey或对其执行阻止Wait的原因Task.
如果您发现自己需要SynchronizationContext,可以使用AsyncContext我的Nito.AsyncEx库; 它基本上只提供了一个async兼容的"主循环" SynchronizationContext.我发现它对Console应用程序和单元测试很有用(VS2012现在内置了对async Task单元测试的支持).
有关的更多信息SynchronizationContext,请参阅我的2月MSDN文章.
在任何时候都不是DoEvents或等同的; 相反,控制流一直返回,并且延续(函数的其余部分)计划在以后运行.这是一个更清洁的解决方案,因为它不会像DoEvents使用时那样导致重入问题.
async/await背后的整个想法是它很好地执行continuation传递,并且不为该操作分配新线程.继续可能在新线程上发生,它可能在同一线程上继续.
| 归档时间: |
|
| 查看次数: |
9075 次 |
| 最近记录: |