在您学习这一点时,重要的是要指出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
/ await
world 中,这种方式不是必需的。相反,您可以通过以下方式将任务显式调度到线程池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
.