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() { this .MoveNext(); } [DebuggerHidden ] private void SetStateMachine (IAsyncStateMachine stateMachine ) { } void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { 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 { void MoveNext () ; void SetStateMachine (IAsyncStateMachine stateMachine ) ; }
一旦AsyncTaskMethodBuilder
执行Start
方法,状态机就会开始启用。状态机通过MoveNext
方法来管理状态,状态机第一次调用MoveNext
方法,会检查Awaiter是否已完成,没有完成则交由ThreadPool来调度,然后改变状态值等待ThreadPool通知,一旦Task完成,状态机第二次执行MoveNext
方法,最终会调用SetResult
方法拿到结果,执行剩下代码,状态机结束。
异步状态机实现原理
总结 Task底层是用了ThreadPool实现异步,简化了异步编程。不要在同步方法前用async修饰,会增加无端性能浪费。