async&await的前世今生
阿新 • • 發佈:2018-01-26
amp efault nco void compiler ges -s lis private
async&await=custom IAsyncStateMachine
async&await是IAsyncStateMachine的語法糖
驗證
分別使用async&await和IAsyncStateMachine遍歷一棵樹,查看二者的線程id和線程上下文標識是否相同
數據結構
public class Node
{
private static List<Node> _nodes = new List<Node>();
private static int _id = 1;
public Node()
{
this.Id = _id++;
_nodes.Add(this);
}
public int Id { get; }
public Node Left { get; set; }
public Node Right { get; set; }
public bool IsLeaf => this.Left == null && this.Right == null;
public bool IsTraveled { get; set; } = false;
public override string ToString()
{
return $"{Left?.Id ?? 0}|{this.Id}|{Right?.Id ?? 0}";
}
}
使用async&await遍歷樹
public static async Task<int> Travle(Node node)
{
node.IsTraveled = true;
if (!node.IsLeaf)
{
Console.WriteLine("線程id:" + Thread.CurrentThread.ManagedThreadId + "|線程上下文標識:" + Thread.CurrentThread.ExecutionContext.GetHashCode() + ":" + await Travle(node.Left));
Console.WriteLine("線程id:" + Thread.CurrentThread.ManagedThreadId + "|線程上下文標識:" + Thread.CurrentThread.ExecutionContext.GetHashCode() + ":" + await Travle(node.Right));
}
return node.Id;
}
使用IAsyncStateMachine遍歷樹
public static Task<int> StateMechineTravle(Node node)
{
StateMechine stateMechine = new StateMechine();
stateMechine.node = node;
stateMechine.builder = AsyncTaskMethodBuilder<int>.Create();
stateMechine.state = -1;
AsyncTaskMethodBuilder<int> next_builder = stateMechine.builder;
next_builder.Start<StateMechine>(ref stateMechine);
return stateMechine.builder.Task;
}
這裏StateMechine是實現IAsyncStateMachine接口的一個類
public struct StateMechine : IAsyncStateMachine
{
public int state;
public AsyncTaskMethodBuilder<int> builder;
public Node node;
private object wrap1;
private object wrap2;
private TaskAwaiter<int> awaiter;
void IAsyncStateMachine.MoveNext()
{
int num = this.state;
int id;
try
{
TaskAwaiter<int> taskAwaiter;
if (num != 0)
{
if (num == 1)
{
taskAwaiter = this.awaiter;
this.awaiter = default(TaskAwaiter<int>);
this.state = -1;
goto IL_1AB;
}
this.node.IsTraveled = true;
if (this.node.IsLeaf)
{
goto IL_20C;
}
this.wrap1 = Thread.CurrentThread.ManagedThreadId;
this.wrap2 = Thread.CurrentThread.ExecutionContext.GetHashCode();
taskAwaiter = Program.StateMechineTravle(this.node.Left).GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.state = 0;
this.awaiter = taskAwaiter;
this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, StateMechine>(ref taskAwaiter, ref this);
return;
}
}
else
{
taskAwaiter = this.awaiter;
this.awaiter = default(TaskAwaiter<int>);
this.state = -1;
}
int arg_CC_0 = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<int>);
object obj = arg_CC_0;
Console.WriteLine(string.Concat(new object[]
{
"線程id:",
this.wrap1,
"|線程上下文標識:",
this.wrap2,
":",
obj
}));
this.wrap1 = null;
this.wrap2 = null;
this.wrap2 = Thread.CurrentThread.ManagedThreadId;
this.wrap1 = Thread.CurrentThread.ExecutionContext.GetHashCode();
taskAwaiter = Program.StateMechineTravle(this.node.Right).GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.state = 1;
this.awaiter = taskAwaiter;
this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, StateMechine>(ref taskAwaiter, ref this);
return;
}
IL_1AB:
int arg_1BA_0 = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<int>);
obj = arg_1BA_0;
Console.WriteLine(string.Concat(new object[]
{
"線程id:",
this.wrap2,
"|線程上下文標識:",
this.wrap1,
":",
obj
}));
this.wrap2 = null;
this.wrap1 = null;
IL_20C:
id = this.node.Id;
}
catch (Exception exception)
{
this.state = -2;
this.builder.SetException(exception);
return;
}
this.state = -2;
this.builder.SetResult(id);
}
[DebuggerHidden]
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
this.builder.SetStateMachine(stateMachine);
}
}
結果
輸入1,使用async&await遍歷樹
輸入2,使用IAsyncStateMachine遍歷樹
可以看出,二者一毛一樣
可見,基於async和await的task不會被多線程調用
示例代碼
https://github.com/snys98/AsyncStateMechineTest
官方資料
https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.compilerservices.iasyncstatemachine?view=netframework-4.7.1
async&await的前世今生