async关键字

我们将async修饰的方法叫做“异步方法”,但是并不意味着方法是异步执行,也不意味着该方法是异步方法。

源码

1
2
3
4
5
static async Task MethodAsync()
{
await Task.Run(()=>Console.WriteLine("asynchronous run"));
Console.WriteLine("synchronous run");
}

反编译代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
private sealed class <MethodAsync>d__1 : IAsyncStateMachine
{
public int <>1__state;

public AsyncTaskMethodBuilder <>t__builder;

private TaskAwaiter <>u__1;

private void MoveNext()
{
int num = <>1__state;
try
{
TaskAwaiter awaiter;
if (num != 0)
{
awaiter = Task.Run(<>c.<>9__1_0 ?? (<>c.<>9__1_0 = new Action(<>c.<>9.<MethodAsync>b__1_0))).GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
<MethodAsync>d__1 stateMachine = this;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
return;
}
}
else
{
awaiter = <>u__1;
<>u__1 = default(TaskAwaiter);
num = (<>1__state = -1);
}
awaiter.GetResult();
Console.WriteLine("synchronous run");
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
return;
}
<>1__state = -2;
<>t__builder.SetResult();
}

void IAsyncStateMachine.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
this.MoveNext();
}

[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
}

void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
this.SetStateMachine(stateMachine);
}
}


[AsyncStateMachine(typeof(<MethodAsync>d__1))]
[DebuggerStepThrough]
private static Task MethodAsync()
{
<MethodAsync>d__1 stateMachine = new <MethodAsync>d__1();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}

通过上面的反编译代码可以看出,只要被async修饰的方法都会生成状态机IAsyncStateMachine的实现和一个操作状态机的同名方法,状态机内部逻辑由AsyncTaskMethodBuilder控制,至于是否是异步取决于方法内有没有await修饰。

await关键字

await关键字会被编译器生成TaskAwaiter去接收异步方法的Task,负责后续与状态机交互,最终Task会被交给ThreadPool执行和调度。

TaskAwaiter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private void MoveNext()
{
int num = <>1__state;
try
{
TaskAwaiter awaiter;
if (num != 0)
{
awaiter = Task.Run(<>c.<>9__1_0 ?? (<>c.<>9__1_0 = new Action(<>c.<>9.<MethodAsync>b__1_0))).GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter;
<MethodAsync>d__1 stateMachine = this;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
return;
}
}
else
{
awaiter = <>u__1;
<>u__1 = default(TaskAwaiter);
num = (<>1__state = -1);
}
awaiter.GetResult();
Console.WriteLine("synchronous run");
}
catch (Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
return;
}
<>1__state = -2;
<>t__builder.SetResult();
}

异步状态机(IAsyncStateMachine)

IAsyncStateMachine接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface IAsyncStateMachine
{
//
// Summary:
// Moves the state machine to its next state.
void MoveNext();
//
// Summary:
// Configures the state machine with a heap-allocated replica.
//
// Parameters:
// stateMachine:
// The heap-allocated replica.
void SetStateMachine(IAsyncStateMachine stateMachine);
}

一旦AsyncTaskMethodBuilder执行Start方法,状态机就会开始启用。状态机通过MoveNext方法来管理状态,状态机第一次调用MoveNext方法,会检查Awaiter是否已完成,没有完成则交由ThreadPool来调度,然后改变状态值等待ThreadPool通知,一旦Task完成,状态机第二次执行MoveNext方法,最终会调用SetResult方法拿到结果,执行剩下代码,状态机结束。

异步状态机实现原理
异步状态机

总结

Task底层是用了ThreadPool实现异步,简化了异步编程。不要在同步方法前用async修饰,会增加无端性能浪费。