15.5.4 【Task实现细节】一个入口搞定一切
如果你反编译过异步方法(我非常希望你会这么做),会看到状态机中的 MoveNext() 方法 非常长,变化非常快,像是一个计算有多少 await 表达式的函数。它包含原始方法中的所有逻辑, 和处理所有状态变换所需要的芭蕾舞步 ① ,以及用来处理整个结果或异常的包装代码。
在手动编写异步代码时,你通常会将后续操作分散到多个方法内:在一个方法内开始,然后 在另一个方法内继续,并且可能在第三个方法中结束。但这样很难处理循环等流控制,对C#编译 器来说更是不可能的。这和生成代码的可读性差是两码事。状态机具有单独的入口,即 MoveNext() 方法。该方法在一开始便投入使用,并且可用于所有 await 表达式的后续操作。每当调用 MoveNext() 方法时,状态机就会通过 state 字段计算出方法要跳转到的位置。在准备计算结果 时,则跳转到方法的逻辑起始位置或 await 表达式的末尾。每个状态机只执行一次操作。实际上, 在方法内部存在一个基于 state 的 switch 语句,每种情况都具有包含不同标签的对应 goto 语句。
MoveNext() 方法一般为以下形式:
void IAsyncStateMachine.MoveNext()
{
//对于声明返回Task<int>的异步方法
int result = default(int);
try
{
bool doFinallyBodies = true;
switch (state)
{
//跳转到正确的位置
}
//方法主体
}
catch (Exception e)
{
state = -;
builder.SetException(e);
return;
}
state = -;
builder.SetResult(result);
}
初始状态始终为 -1 ,方法执行时状态也是 -1 (与等待时被暂停相反)。非负值均表示一个后 续操作的目标。状态机在结束时状态为 -2 。在调试配置下创建的状态机中,你会看到一个指向 -3 状态的引用——此状态是我们未曾预料到的。退化的 switch 语句会导致糟糕的调试体验,而 -3 状态即是为避免该退化语句的出现而存在的。
在方法执行过程中,在原始异步方法的 return 语句处,会设置 result 变量。然而在到达方 法的逻辑末尾时,将其用于 builder.SetResult() 的调用。即使是非泛型的 AysncTask MethodBuilder 和 AsyncVoidMethodBuilder 类型,也包含 SetResult() 方法。前者表示对 于从骨架方法返回的任务来说,该方法已经完成;后者则表示原始的 SynchronizationContext 已经完成。(异常会以同样的方式向原始的 SynchronizationContext 传播。这是一种相当丑陋 的跟踪方式,但却对必须使用 void 方法的场景提供了一种解决方案。)
doFinallyBodies 变量用于计算执行过程离开 try 块的作用域时,原始代码中的 finally 块(包括 using 或 foreach 语句中的隐式 finally 块)是否应该执行。理论上,只有以正常方式 离开 try 块的作用域时,我们才希望执行 finally 块。如果我们只是从之前为awaiter附加了后续 操作的方法中返回,由于该方法逻辑上已经“暂停”了,因此我们不希望再执行 finally 块。 finally 块均位于相关的 try 块之后,并出现在代码方法部分的 Main 主体中。
从原始异步方法的角度来看,大多方法体都是可识别的。当然,你需要习惯于所有局部变量 都作为状态机的实例变量,但这并不是什么难事。正如你所想的那样,棘手之处是 await 表达式。
15.5.4 【Task实现细节】一个入口搞定一切的更多相关文章
- Jquery一个slideToggle搞定div的隐藏与显示
Jquery一个slideToggle搞定div的隐藏与显示 <!DOCTYPE html> <html> <head> <script src=" ...
- 将你的前端应用打包成docker镜像并部署到服务器?仅需一个脚本搞定
1.前言 前段时间,自己搞了个阿里云的服务器.想自己在上面折腾,但是不想因为自己瞎折腾而污染了现有的环境.毕竟,现在的阿里云已经没有免费的快照服务了.要想还原的话,最简单的办法就是重新装系统.而一旦重 ...
- 一个类搞定UIScrollView那些事儿
前言 UIScrollView可以说是我们在日常编程中使用频率最多.扩展性最好的一个类,根据不同的需求和设计,我们都能玩出花来,当然有一些需求是大部分应用通用的,今天就聊一下以下需求,在一个categ ...
- 一个包搞定中文数据集: datasetstore
工作中,总是要使用各种中文数据集,每次使用数据集都要花费不少的时间进行寻找,写预处理代码,结合不同的模型和框架做出相应的处理.有的时候好不容易找到合适的数据集,但是却因为网络问题,无法下载,下载了很长 ...
- 如何让两个div在同一行显示?一个float搞定
最近在学习div和css,遇到了一些问题也解决了很多以前以为很难搞定的问题.比如:如何让两个div显示在同一行呢?(不是用table表格,table对SE不太友好)其实,<div> 是一个 ...
- iOS之下拉放大,上推缩小,一个方法搞定
先来看看效果吧. 讲讲大概的实现思路:1、创建头部的视图和tableview,需要注意的是tableview要设置contentInset,contentInsent 的顶部要和头部视图的背景图的高度 ...
- 收不到Win10正式版预订通知?一个批处理搞定
目前,已经有不少Win7.Win8.1用户在系统右下角收到Win10正式版的预订提示窗口.点击接受预订后,系统会将Win10正式版所需的安装文件提前下载好,7月29日正式发布的时候,就可以第一时间升级 ...
- 一个类搞定UIScrollView那些事
前言 UIScrollView可以说是我们在日常编程中使用频率最多.扩展性最好的一个类,根据不同的需求和设计,我们都能玩出花来,当然有一些需求是大部分应用通用的,今天就聊一下以下需求,在一个categ ...
- H5 拖拽,一个函数搞定,直接指定对象设置可拖拽
页面上,弹个小窗体,想让它可以拖拽,又不想 加载一堆js,就简单的能让他可以拖动? 嗯,下面有这样一个函数,调用下就好了! 1. 先来说说 H5的 拖拽 在 HTML5 中,拖放是标准的一部分,任何元 ...
随机推荐
- OpenCV使用GPU
在使用OpenCV2.4.x的时候,以为不用重新编译可以直接使用GPU模块,不过在我使用的时候,发现使用getCudaEnabledDeviceCount()的时候,总是获得是0,于是重新编译Open ...
- HTML5:去除IE10中输入框和密码框的X按钮和小眼睛
在IE10和之后的IE版本中,当在输入框和密码框中输入的时候,后面会自动出现X按钮和小眼睛,如下图所示: 令人苦恼的是,这个效果只有IE才有,其它浏览器是没有这个功能的.为了统一,我们就需要去掉这个 ...
- [ javascript ] getElementsByClassName与className和getAttribute!
对于javascript中的getElementsByClassName 在IE 6/7/8 不支持问题. 那么须要模拟出getElementsByClassName 须要採用className属性 ...
- Python爬虫抓取csdn博客
昨天晚上为了下载保存某位csdn大牛的所有博文,写了一个爬虫来自己主动抓取文章并保存到txt文本,当然也能够 保存到html网页中. 这样就能够不用Ctrl+C 和Ctrl+V了,很方便.抓取别的站点 ...
- Handler类和Handler,Loop,MessageQueue的工作原理
原文地址:http://blog.csdn.net/xiyangyang8/article/details/50754771 Handler类的作用主要有两种: 1.在新启动的线程中发送消息. 2.在 ...
- Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节【转】
本文转载自:http://blog.csdn.net/mu0206mu/article/details/7465439 Android系统Recovery工作原理之使用update.zip升级过程分 ...
- 【POJ 2230】 Watchcow
[题目链接] http://poj.org/problem?id=2230 [算法] 欧拉回路 [代码] #include <algorithm> #include <bitset& ...
- 联想Thinkpad L460安装Win7 64位
单位发了L460,自带的系统为win10,但是涉及到很多工作以及客户都是在win7环境下,所以必须安装win7的系统,经过一番折腾,终于装好了. 主要顺序如下: 1,制作WINPE启动盘,如大白菜,老 ...
- php的self和this
<?phpclass ss{ public static $code; public function __construct( $code ) { self::$code=$code; //这 ...
- 1.ArcGis几何图形之几何计算
/// <summary> /// 检测几何图形A是否包含几何图形B /// </summary> /// <param name="pGeometryA&qu ...