了解C#5 async / await中的上下文
我是否正确async / await本身与并发/并行无关,只不过是继续传递样式(CPS)实现? 真正的线程是由await
传递/恢复的SynchronizationContext
实例执行的?
如果这是正确的,我有关于SynchronizationContext
的以下问题:
它保证在同一个线程上执行延续。
但是,是否有任何保证线程的上下文信息是持久的? 我的意思是Name
, CurrentPrincipal
, CurrentCulture
, CurrentUICulture
等。它依赖于框架(ASP.NET,WinForms,WCF,WPF)吗?
我是否正确async / await本身与并发/并行无关,只不过是CPS实现?
好吧, async
/ await
是一个使用CPS的重写,所以你的核心理解是正确的。
关于“并发”和“并行”,我会说它确实能够实现并发性; 您可以同时启动多个async
操作,这些操作都在“飞行中”。 使用Task.WhenAll
和Task.WhenAny
很容易。
此外,尽管async
本身并不意味着“multithreading”,但Task.Run
确实可以实现简单的async
兼容multithreading
真正的线程是由等待传递/恢复的SynchronizationContext实例执行的?
可以这样想:CPS重写创建的延续必须在某个地方运行。 捕获的“异步上下文”可用于安排继续。
附注:捕获的上下文实际上是SynchronizationContext.Current
除非它为null ,在这种情况下捕获的上下文是TaskScheduler.Current
。
另一个重要的注意事项:捕获和恢复上下文实际上取决于“awaiter”对象。 因此,默认情况下,如果您await
Task
(或任何其他内置的等待),将捕获并恢复上下文。 但是,如果await
ConfigureAwait(false)
的结果,则不会捕获上下文。 同样,如果您await
自己的自定义等待,它将不会捕获上下文(除非您将其编程)。
但是,是否有任何保证线程的上下文信息是持久的? 我的意思是Name,CurrentPrincipal,CurrentCulture,CurrentUICulture等。
SynchronizationContext
与ExecutionContext
不同。 简化的答案是ExecutionContext
始终“流动”,因此CurrentPrincipal
流(如果没有,则可能是安全问题,这就是为什么不流动ExecutionContext
API总是以Unsafe
结尾)。
在UI应用程序中,文化不会流动,但默认情况下,所有线程都是相同的。 除非您在同一个线程上恢复(例如,使用UI SynchronizationContext
),否则Name
肯定不会流动。
为了进一步阅读,我建议从我自己的async
/ await
教程开始 ,然后是官方的async
/ await
FAQ 。 然后看一下Stephen Toub关于ExecutionContext
与SynchronizationContext
的博客文章 。
您还可以找到我的SynchronizationContext
文章 。
不, async
/ await
关键字与并发有关。 async
/ await
基本上将您的方法代码包装到任务和继续中。 要查看编译器生成的确切转换(使用任务并行库),请反汇编一些代码段。 async
/ await
使用的这种转换与下面的例子“相似”(但不完全相同!)
async Task TaskOfTResult_MethodAsync() { int hours; // . . . // Return statement specifies an integer result. return hours; } // Calls to TaskOfTResult_MethodAsync Task returnedTaskTResult = TaskOfTResult_MethodAsync(); int intResult = await returnedTaskTResult; // or, in a single statement int intResult = await TaskOfTResult_MethodAsync();
这是近似转换为
private int Result() { int hours; // . . . // Return statement specifies an integer result. return hours; }
你在等待方法之外等待返回的地方
int? hours = null; Task task = null; task = Task.Factory.StartNew (() => Result()); task.ContnueWith(cont => { // Some task completion checking... hours = task.Result; }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);
或者,您可以将TPL代码放入Result
方法中
private int ResultAsync() { int? hours = null; Task task = null; task = Task.Factory.StartNew (() => { int hours; // . . . // Return statement specifies an integer result. return hours; }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current); try { return task.Result; } catch (AggregateException aggEx) { // Some handler method for the agg exception. aggEx.Handle(HandleException); } }
SynchronizationContext
不保证将在async
/ awate
代码的同一线程上执行awate
。 但是,您可以通过SynchronisationContex
关键字使用TPL代码设置上下文。
上述就是C#学习教程:了解C#5 async / await中的上下文分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/983827.html