任何 await 表达式均表示执行路径的一个分支。首先,被等待的异步操作得到一个awaiter,
然后检查其 IsCompleted 属性。若返回 true ,即可立即获得结果并继续。否则,需进行以下处理。
   存储awaiter,以供后面使用。
   更新状态,以表示从哪里继续。
   为awaiter附加后续操作。
   从 MoveNext() 返回,确保不会执行任何 finally 块。
  然后,在调用后续操作时,需跳转到正确的地方,获取awaiter并重置状态,然后继续。
例如,代码清单15-11中的第一个 await 表达式即:

                await Task.Delay(unicode);

  所生成的代码如下所示:

                         TaskAwaiter localTaskAwaiter = Task.Delay(unicode).GetAwaiter();
if (localTaskAwaiter.IsCompleted)
{
goto FirstAwaitCompletion;
}
state = ;
taskAwaiter = localTaskAwaiter;
builder.AwaitUnsafeOnCompleted(ref localTaskAwaiter, ref this);
doFinallyBodies = false;
return;
FirstAwaitRealContinuation:
localTaskAwaiter = taskAwaiter;
taskAwaiter = default(TaskAwaiter);
state = -;
FirstAwaitCompletion:
localTaskAwaiter.GetResult();
localTaskAwaiter = default(TaskAwaiter);

如果等待的操作有返回值(如使用 HttpClient 分配 await client.GetStringAsync(...) 的结果),那么上述代码末尾处的 GetResult() 调用将得到该值。

AwaitUnsafeOnCompleted 方法将后续操作附加给awaiter, MoveNext() 方法开头的 switch 语句可确保再次执行 MoveNext() 时,将控制传递给 DemoAwaitContinuation 。

  说明 AwaitOnCompleted 和 AwaitUnsafeOnCompleted 在此前展示的一组接口中, IAwaiter<T> 扩展了 INotifyCompletion 及其 OnCompleted 方法,此外还扩展了 ICriticalNotifyCompletion 接口及其 UnsafeOnCompleted 方法。状态机为实现 ICriticalNotifyCompletion 的 awaiter 调用 builder.AwaitUnsafeOnCompleted ,或 为只实现 INotifyCompletion 的 awaiter 调用 builder.AwaitOnCompleted 。15.6.4节 在讨论可等待模式如何与上下文交互时,会介绍这两个调用间的区别。

  注意,编译器为awaiter消除了局部变量和实例变量,这样就可以适时进行垃圾回收。 如果单个的 await 表达式也可以像这样找到块,则生成代码在反编译模式下不会太难以阅 读。由于CLR的限制,可能会存在较多的 goto 语句(及相应的标签),但在我看来, await 模式 才是最难理解的。 还有一个概念必须加以解释,那就是状态机中神秘的 stack 变量。

最新文章

  1. NoSql数据库初探-mongoDB读操作
  2. MongoDB学习笔记八:复制
  3. Uva 11059 Maximum Product
  4. poj 1741 Tree(点分治)
  5. Django之Cookie与Session
  6. 【Android Developers Training】 103. 查询当前地点
  7. ubuntu16 ftp 服务 vsftp 配置
  8. Open source operational tools
  9. 【网摘】EasyUI常用控件禁用启用方法
  10. Jason Wang: 结对编程 CountWord(第三次作业)
  11. ORM以及Django使用ORM创建表
  12. 断断续续Python看到现在
  13. 开放标准-http://www.open-std.org/
  14. 《笔记》Python itertools的groupby分组数据处理
  15. 校内模拟赛 Zbq&#39;s Music Challenge
  16. Keras 实现一个简单GAN
  17. VIP之Clipper
  18. Logistic回归中损失函数求导证明过程
  19. 关于.NetCore 2.0 迁移到2.1的一些建议和问题
  20. testng入门教程16数据驱动(把数据写在xml)

热门文章

  1. Libevent 学习笔记 (1)——Libevent 2.0安装与简单演示样例
  2. IntelliJ IDEA中出现could not auto wired错误提示处理方式
  3. 1.7-BGP⑤
  4. Lucene5学习之使用MMSeg4j分词器
  5. pcm数据生成wav文件
  6. Hadoop - YARN 启动流程
  7. HDU 5534/ 2015长春区域H.Partial Tree DP
  8. bzoj2935 [Poi1999]原始生物——欧拉回路
  9. Mock实现模拟python的对象
  10. KindEditor文本编辑框的实现