内容简介:其实这篇文章的内容可以参考《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
,以上三步就要在状态机中重复几次。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Text Algorithms
Maxime Crochemore、Wojciech Rytter / Oxford University Press / 1994
This much-needed book on the design of algorithms and data structures for text processing emphasizes both theoretical foundations and practical applications. It is intended to serve both as a textbook......一起来看看 《Text Algorithms》 这本书的介绍吧!