async/await
是极好的异步编程的语法糖,其实是编译器生成了状态机StateMachine,可是StateMachine又是如何在任务完成之后恢复的呢?
可以这么看,就是await后的代码由编译器编译成了一个回调方法,在状态机切换后就执行这个回调——听上去和传统的异步很像吧?其实就是通过编译器对异步回调施加了魔法而已。
顶楼的回答是具体的细节过程,如果只想知道回调的话,只要知道状态机是用来管理异步执行状态的,状态切换时会调用特定回调,而这个回调是编译器生成的后续执行代码。
坐等大神解答
摘录 Async Await and the Generated StateMachine 中的一段文字:
What really happens is actually something like this:
- On compile time:
- A
struct
calledStateMachine
is generated- Contains fields to save function local state
- A
moveNext
function is created which holds the entire code- The code is fragmented by await calls into several cases (machine states)
- A calling code which creates and initializes this machine replaces our async function code.
- On Runtime:
- A task is created to run the machine code:
- Local variables are “lifted” into the state machine as fields.
- Code is run until await
- A awaited function's task is run
- Machine state is set to next state so next code fragment will run on wakeup
- A wake-up event is scheduled
MoveNext
function returns (Thread is released to do other stuff (update UI))- When wakeup call is issued by OS:
- Thread which handles the await continuation is called
CurrentSyncContext
is used to pick the correct thread to run it on.
- This behavior can be changed by using: await
task.ConfigureAwait(false);
- Next code segment is run since next state was set before yielding control
- Another await is scheduled, [etc.]
当你执行一个async的方法时,这个时候就依赖于状态机中一个很简单的switch来控制流程。一般情况(IO密集)下,请求会直接进入到内核,同时由内核提供异步实现(系统提供),然后你的请求就已经由最底层的驱动来执行(由于是异步,此时此请求可能处于不同状态,排队,已经在执行,完毕等,但是不会阻止线程执行),同时执行线程会立即知道这个任务处于pending状态,因此线程资源则可以处理其他事情。同时会返回一个Task/Task<T>给调用方(这也是状态机中初始状态的case的流程)。
之后就是漫长的等待过程(相对前面处理的消耗)直到最底层驱动收取到响应,然后驱动会告知cpu数据已经准备好了,cpu会在合适的时候对数据做解包操作。然后从内核返回用户模式进入状态机中的switch(MoveNext方法,state用于记录状态),最终执行相应的代码。
cpu密集型的逻辑有些不同,在判断出此种类型后(也可能是你代码中直接给task的各种hint),此种请求会直接进入线程池队列(这里我不太明确),同时返回Task/Task<T>。然后主线程(启动task的线程)会继续后续逻辑,直到碰到针对这个task的await。于此同时通过线程池分配的线程对委托进行计算,当计算完毕或者当碰到await,底层会通过task对应的TaskAwaiter判断是否结束(如已经complete则交由状态机最后一个状态完成相应工作,否则开始通过自旋等待升级为ManualResetEventSlim(轻量级的ManualResetEvent)等待),最后拿到结果。
您说的是整个异步的流程模型,而我想知道的是,这个StateMachine是如何实现的?
任务完成之后,它是如何恢复过来,继续往下执行的呢?关注点是如何实现的。
最后,再次表示感谢。