await后面的代码在哪里运行

时间:2016-05-05 21:27:37

标签: c# asynchronous async-await

如果你有这样的代码:

var result = await task;
mycode(result);
  • 如果任务已经完成,mycode是否会始终同步运行?

  • 如果任务尚未完成,我的代码在什么情况下不会与完成同步执行? (等待时SynchronizationContext不为null,完成时不同,将为1)

2 个答案:

答案 0 :(得分:3)

我在博客上解释了details of await semantics

  

如果任务已经完成,mycode是否会始终同步运行?

是。 await运算符首先检查任务是否已完成;如果有,则继续同步执行。

如果任务尚未完成,则await将创建任务延续,以在任务完成时继续执行当前方法。当await执行此操作时,默认情况下它将捕获当前的“上下文”并在该上下文中恢复该方法。此“上下文”为SynchronizationContext.Current,除非为null,在此情况下为TaskScheduler.Current

  

如果任务尚未完成,我的代码在什么情况下不会与完成同步执行? (等待时SynchronizationContext不为null,完成时不同,将为1)

await always schedules its continuations with the ExecuteSynchronously flag(这是我博客上描述的未记录的实施细节)。但是,there's some situations where ExecuteSynchronously doesn't execute synchronously,最值得注意的是,TaskScheduler捕获的await确定它与完成线程不兼容 - 但也有其他情况,如完成线程已经中止,或者如果使用了太多的堆栈。

即使 同步执行,正如您所指出的那样,如果SynchronizationContext抓取了await,它将决定它是否与当前上下文兼容,如果此检查通过,则只有实际同步执行。

简而言之,你不能假设它总是同步执行。

答案 1 :(得分:1)

  

如果任务已经完成,mycode是否会始终同步运行?

是的,确实如此。

  

如果任务尚未完成,我的代码在什么情况下不会与完成同步执行?

如果任务没有完成,那么代码跟随await的代码很可能会被线程池的另一个线程执行。实际上,当看到async / await时,编译器会创建状态机并使用continuation来说明代码的执行方式。在运行时,当CLR注意到任务尚未完成时,暂停此时代码的执行并释放运行代码的线程。稍后,当任务完成时,CLR会获得另一个线程或相同的线程来继续执行代码。