内容简介:其实这篇文章的内容可以参考《CLR via C#》里的第28章,不过总觉得书上的还不够直观,所以干脆自己来整理一下好了。新建一个控制台项目,代码如下,三个非常简单的方法。现在用
其实这篇文章的内容可以参考《CLR via C#》里的第28章,不过总觉得书上的还不够直观,所以干脆自己来整理一下好了。
新建一个控制台项目,代码如下,三个非常简单的方法。
static async Task<string> MyMethodAsync(int argument) { var t1 = await GetType1(); var t2 = await GetType2(); return "Complete"; } static async Task<Type> GetType1() { await Task.Run(() => { Console.WriteLine("GetType1"); }); return typeof(string); } static async Task<Type> GetType2() { await Task.Run(() => { Console.WriteLine("GetType2"); }); return typeof(int); }
现在用 ILSpy
将其转换为 C# 4.0
的代码之后(因为 C# 4.0
没有 async
await
,所以能看到状态机),我们来看看状态机的原理:
代码经过可读性优化,并非原版。
/* 指出这是一个异步方法,并指出状态机的实现是哪个 class\struct */ [AsyncStateMachine(typeof(<MyMethodAsync>d__1))] [DebuggerStepThrough] private static Task<string> MyMethodAsync(int argument) { // 创建状态机实例并初始化 <MyMethodAsync>d__1 stateMachine = new <MyMethodAsync>d__1(); stateMachine.argument = argument; // 将方法实参拷贝到状态机的字段上 // 创建 builder ,从这个方法存根(我觉得理解为变量即可)上返回 Task<string> stateMachine.t__builder = AsyncTaskMethodBuilder<string>.Create(); stateMachine.m_state = -1; // 设置状态的初始位置 // 开始执行状态机 stateMachine.t__builder.Start(ref stateMachine); return stateMachine.t__builder.Task; // 返回状态机的 Task } // 这两个方法不重要,当摆设展示下结构即可 [AsyncStateMachine(typeof(<GetType1>d__2))] [DebuggerStepThrough] private static Task<Type> GetType1() [AsyncStateMachine(typeof(<GetType2>d__3))] [DebuggerStepThrough] private static Task<Type> GetType2() /* 这是状态机本身,Release 下是 struct 原因:https://stackoverflow.com/questions/23609110/why-are-awaiters-async-await-structs-and-not-classes-can-classes-be-used */ [CompilerGenerated] private sealed class <MyMethodAsync>d__1 : IAsyncStateMachine { /* 当前状态机的位置 */ public int m_state; /* 状态机的 builder */ public AsyncTaskMethodBuilder<string> t__builder; /* MyMethodAsync 方法的实参和局部变量此时会变成状态机的字段 所以一共有三个 */ public int argument; private Type m_t1; private Type m_t2; /* 每个 awaiter 类型一个字段,我这里 GetType1 跟 GetType2 都返回的是 Type 类型 所以这里只有一个字段 当你的方法中涉及到多个 Awaiter 类型时,就会有多个字段,但任何时候只有最近执行的、完成的那一个字段是重要的 */ private TaskAwaiter<Type> m_awaiterType1; /* 这是状态机方法 */ void IAsyncStateMachine.MoveNext() { int num = m_state; string result; // 结果值 try // 编译器插入 try 块保证状态机的任务完成 { TaskAwaiter<Type> awaiter1; TaskAwaiter<Type> awaiter2; switch (num) { /* 这里理解成case -1就行了,意为状态机第一次执行 也就是 var t1 = await GetType1(); */ default: awaiter1 = GetType1().GetAwaiter(); // 调用 GetType1 方法并拿到其 Awaiter if (!awaiter1.IsCompleted) // 这里做判断是避免多次执行 { num = (m_state = 0); // 等一会儿返回状态机时走到哪个位置去 m_awaiterType1 = awaiter1; // 保存 awaiter 以便将来返回 stateMachine = this; /* 告诉 awaiter 在 GetType1 的异步方法执行完毕后,调用 MoveNext 具体一点,这句代码会调用 awaiterType1 的 OnCompleted 它会在被等待的任务上调用 ContinueWith(t=> MoveNext()... 表示任务完成后调用 MoveNext 方法重返状态机 */ t__builder.AwaitUnsafeOnCompleted(ref awaiter1, ref stateMachine); /* 线程返回至调用者 */ return; } goto case unNamed; /* GetType1 方法异步完成了 */ case 0: awaiter1 = m_awaiterType1; // 恢复最新的 awaiter m_t1 = awaiter1.GetResult(); // 获取 GetType1 方法的结果 // 开始调用 GetType2 awaiter2 = GetType2().GetAwaiter(); if (!awaiter2.IsCompleted) { num = (m_state = 1); // 下一次 MoveNext 时走到 case 1 中 m_awaiterType1 = awaiter2; t__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine); return; } break; case 1: { awaiter2 = m_awaiterType1; // 恢复最新的 awaiter m_t2 = awaiter2.GetResult(); // 获取 GetType2 方法的结果 result = "Complete"; // 设置 MyMethodAsync 方法最终的返回结果 // 注意这里没有 break,还要继续执行 } } catch (Exception exception) { // 有异常:通过设置异常来完成状态机的 Task t__builder.SetException(exception); return; } // 无异常:通过返回结果来完成状态机的 Task t__builder.SetResult(result); } }
状态机总结
简单总结以下状态机的几个工作要点:
-
安排好
awaiter
之后就 返回原调用线程避免阻塞 -
在安排时
更新状态机恢复之后需要执行的位置(
m_state
) -
安排后在
awaiter
的任务上调用ContinueWith(t=> MoveNext())
来以便返回状态机
可以简单理解为你的 async
方法中有几个 await
,以上三步就要在状态机中重复几次。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Security Testing Cookbook
Paco Hope、Ben Walther / O'Reilly Media / 2008-10-24 / USD 39.99
Among the tests you perform on web applications, security testing is perhaps the most important, yet it's often the most neglected. The recipes in the Web Security Testing Cookbook demonstrate how dev......一起来看看 《Web Security Testing Cookbook》 这本书的介绍吧!