提问者:小点点

使用Async/Await的任务继续并行执行


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

我认为情况就是这样,因为continuations被发布在默认的任务调度程序上(console app中没有SynchronizationContext,它是线程池。

我知道Async/Await构造不会构造任何附加线程。仍然应该至少有一个线程由线程池构建每个CPU,因此,如果继续发布在线程池上,它可以在不同的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方法,那么异步方法的延续代码(在await之后)有可能在不同的CPU线程上并行运行吗?即在这种情况下我是否需要照顾线程同步,并同步对字段“I”的访问?


共2个答案

匿名用户

是的,您应该将线程同步逻辑放在周围,因为有可能多个线程同时执行之后的代码。

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

匿名用户

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

每个方法都是同步启动的,因此您的循环将在同一个线程上执行的开头。假设返回不完整的,则将在线程池上调度继续。

因此的每个调用都可以并行地继续。