如果你有这样的代码:
var result = await task;
mycode(result);
如果任务已经完成,mycode是否会始终同步运行?
如果任务尚未完成,我的代码在什么情况下不会与完成同步执行? (等待时SynchronizationContext不为null,完成时不同,将为1)
答案 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会获得另一个线程或相同的线程来继续执行代码。