在您学习这一点时,重要的是要指出Task TPLTask 使用的与 async/await 使用的完全不同,即使它们是相同的类型。例如,TPL 通常使用父/子任务,但async/await不使用。
TPL 使用任务调度程序来执行其任务。正如 Dennis 指出的那样,TaskScheduler.FromCurrentSynchronizationContext将为您提供一个任务调度程序,用于Post在当前SynchronizationContext执行其任务。
async/await通常不使用任务调度程序。我的博客上有一篇介绍性async/await帖子,其中包含上下文信息,我还在我的MSDN 文章中简要提到了它(不过很容易忽略)。本质上,当一个async方法在 a 处挂起时await,默认情况下它将捕获当前SynchronizationContext(除非它是null,在这种情况下它将捕获当前TaskScheduler)。当async方法恢复时,它会在该上下文中恢复执行。
Dennis 指出了将任务调度到 current 的 TPL 方式SynchronizationContext,但在async/ awaitworld 中,这种方式不是必需的。相反,您可以通过以下方式将任务显式调度到线程池Task.Run:
async Task MyMethodAsync()
{
// Whee, on a SynchronizationContext here!
await Task.Run(() => { }); // Ooo, on the thread pool!
// Back on the SynchronizationContext ...
// ... automagically!
}
我写SynchronizationContext这篇文章正是因为 MSDN 文档太少了。我的博客上有更多信息,但所有重要信息都在 MSDN 文章中。许多类型使用AsyncOperation而不是SynchronizationContext直接使用;最好的文档隐藏在 EAP 文档(“线程和上下文”部分)下。但我还应该指出,由于async/ await,EAP 实际上已经过时,所以我不会使用AsyncOperation(or SynchronizationContext) 编写代码 - 除非我实际上是在编写自己的 SynchronizationContext.