• 15.5.5 【Task实现细节】围绕 await 表达式的控制


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

                    await Task.Delay(unicode);

      所生成的代码如下所示:

     1                         TaskAwaiter localTaskAwaiter = Task.Delay(unicode).GetAwaiter();
     2                         if (localTaskAwaiter.IsCompleted)
     3                         {
     4                             goto FirstAwaitCompletion;
     5                         }
     6                         state = 0;
     7                         taskAwaiter = localTaskAwaiter;
     8                         builder.AwaitUnsafeOnCompleted(ref localTaskAwaiter, ref this);
     9                         doFinallyBodies = false;
    10                         return;
    11                     FirstAwaitRealContinuation:
    12                         localTaskAwaiter = taskAwaiter;
    13                         taskAwaiter = default(TaskAwaiter);
    14                         state = -1;
    15                     FirstAwaitCompletion:
    16                         localTaskAwaiter.GetResult();
    17                         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 变量。

  • 相关阅读:
    mysql grant命令
    appache ab测试高并发
    转:windows下定时执行备份数据库
    linux设置定时任务
    YII学习总结6(模板替换和“拼合”)
    YII学习总结5(视图)
    YII学习总结4(cookie操作)
    把字符串转换成整数
    不用加减乘除做加法
    求1+2+3+4+...+n
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10128230.html
Copyright © 2020-2023  润新知