这取决于上下文。在WinForms应用程序中,如果你等待UI线程的一些操作,控制权会再次回到UI线程。但在控制台应用程序中,则可能不会。
someTask.ConfigureAwait(false)
时,就会发生这种情况。 - svickEric Lippert的回答非常优秀,我只是想进一步描述async
并发性。
简单的“串行”方法是在每次只有一个操作时使用 await
:
static void Process()
{
Thread.Sleep(100); // Do CPU work.
}
static async Task Test()
{
await Task.Run(Process);
await Task.Run(Process);
}
在这个例子中,Test
方法会将Process
排入线程池,当它完成后,会再次将Process
排入线程池。 Test
方法在大约200毫秒后完成。在任何时候,只有一个线程真正推进进度。Task.WhenAll
:static void Process()
{
Thread.Sleep(100); // Do CPU work.
}
static async Task Test()
{
// Start two background operations.
Task task1 = Task.Run(Process);
Task task2 = Task.Run(Process);
// Wait for them both to complete.
await Task.WhenAll(task1, task2);
}
在这个例子中,Test
方法将Process
两次排队到线程池中,并等待它们都完成。在大约100毫秒后,Test
方法将完成。
Task.WhenAll
(和Task.WhenAny
)是通过async
/await
引入以支持简单的并行处理。然而,如果您需要更高级的内容(真正的CPU绑定并行处理更适合TPL),则TPL仍然可用。TPL与async
/await
很好地协作。async
博客文章中涵盖了基本的async
并行处理,以及Eric所提到的“上下文”。GetAwaiter
方法),如果您使用await
关键字调用该方法,编译器可以生成消耗该对象的代码。您也可以自由地调用这样的方法without使用await关键字,并显式地消耗该对象。async
和await
是基于TPL的,因此它们应该非常相似。默认情况下,您应该将它们视为在单独的线程上运行。