我想知道异步/等待代码生成器是否分析了这一事实
延续实际上是同步使用的TaskContinuationOptions.ExecuteSynchronously
哪里可以...而我
未能在 IL 生成的代码中找到此内容。
Whether await
延续-without ConfigureAwait(continueOnCapturedContext: false
)- 异步或同步执行取决于线程上是否存在同步上下文,该线程在执行代码时执行代码await
观点。如果SynchronizationContext.Current != null
,进一步的行为取决于实施SynchronizationContext.Post
.
例如,如果您位于 WPF/WinForms 应用程序的主 UI 线程上,您的延续将在同一线程上执行,但仍然异步地,在消息循环的某些未来迭代中。它将通过发布SynchronizationContext.Post
。前提是先行任务已在线程池线程或不同的同步上下文上完成(例如,为什么每个 Dispatcher.BeginInvoke 回调都有唯一的同步上下文? https://stackoverflow.com/questions/22217477/why-a-unique-synchronization-context-for-each-dispatcher-begininvoke-callback).
如果先行任务已在具有相同同步上下文的线程(例如 WinForm UI 线程)上完成,则await
继续将被执行同步地(内联)。SynchronizationContext.Post
在这种情况下不会使用。
在没有同步上下文的情况下,await
继续将被执行同步地在前面的任务已完成的同一线程上。
这就是它与你的不同之处ContinueWith
with TaskContinuationOptions.ExecuteSynchronously
实现,它根本不关心初始线程或完成线程的同步上下文,并且总是同步执行延续(有此行为的例外情况 http://blogs.msdn.com/b/pfxteam/archive/2012/02/07/10265067.aspx, 尽管如此)。
您可以使用ConfigureAwait(continueOnCapturedContext: false)
更接近所需的行为,但其语义仍然不同于TaskContinuationOptions.ExecuteSynchronously
。事实上,它指示调度程序not在具有任何同步上下文的线程上运行延续,因此您可能会遇到以下情况ConfigureAwait(false)
将延续推入线程池 https://stackoverflow.com/questions/22672984/configureawait-pushes-the-continuation-to-a-pool-thread,而您可能一直期望同步执行。
还相关:重访Task.ConfigureAwait(continueOnCapturedContext: false). https://stackoverflow.com/questions/28410046/revisiting-task-configureawaitcontinueoncapturedcontext-false?lq=1