任务继续与async / await并行执行

在使用async / await结构的控制台应用程序的上下文中,我想知道“continuation”是否可以在不同CPU上的多个线程上并行运行。

我认为就是这种情况,因为延迟发布在默认任务调度程序(控制台应用程序中没有SynchronizationContext)上,这是线程池。

我知道async / await构造不构造任何额外的线程。 仍然应该由线程池为每个CPU构建至少一个线程,因此如果在线程池上发布了continuation,它可以在不同的CPU上并行调度任务延续…这就是我的想法,但出于某种原因我昨天对此我真的很困惑,我不再那么肯定了。

这是一些简单的代码:

public class AsyncTest { int i; public async Task DoOpAsync() { await SomeOperationAsync(); // Does the following code continuation can run // in parrallel ? i++; // some other continuation code .... } public void Start() { for (int i=0; i<1000; i++) { var _ = DoOpAsync(); } // dummy variable to bypass warning } } 

SomeOperationAsync本身不会创建任何线程,让我们说为了示例它只是依赖于I / O完成端口异步发送一些请求,因此根本不会阻塞任何线程。

现在,如果我调用将发出1000个异步操作的Start方法,是否可以在不同的CPU线程上并行运行async方法的延续代码(在await之后)? 即在这种情况下我是否需要处理线程同步并同步访问字段“i”?

是的,您应该在i++周围放置线程同步逻辑,因为多个线程可能会在await同时执行代码。

作为for循环的结果,将创建任务数。 这些任务将在不同的线程池线程上执行。 完成这些任务后,将继续执行连续,即等待之后的代码,将在不同的线程池线程上再次执行。 这使得多个线程可以同时执行i ++

您的理解是正确的:在控制台应用程序中,默认情况下,由于默认的SynchronizationContext将继续将延迟调度到线程池。

每个async方法都会async启动,因此for循环将在同一个线程上执行DoOpAsync的开头。 假设SomeOperationAsync返回一个不完整的Task ,则将在线程池上安排continuation。

因此, DoOpAsync每个调用可以并行继续。