使用async/await的任务继续并行执行

7
在使用async/await构造的控制台应用程序上下文中,我想知道是否可能让"续体"在不同CPU上的多个线程上并行运行。
我认为情况是这样的,因为续体被发布在默认任务调度程序(控制台应用程序中没有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 完成端口,因此根本不会阻塞任何线程。

现在,如果我调用 Start 方法来发出 1000 个异步操作, async 方法的后续代码(await 后)是否有可能在不同的 CPU 线程上并行运行?也就是说,在这种情况下,我需要注意线程同步并同步访问字段“i”吗?


你想让它们并行运行吗? 如果是这样,同步所有调用就很容易了,在 "Start" 中只需 await DoOpAsync - Servy
2个回答

6

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

由于你的for循环,将创建大量任务。这些任务将在不同的线程池线程上执行。一旦这些任务完成,即在await之后,继续执行即代码将再次在不同的线程池线程上执行。这使得多个线程可以同时执行i++。


6
您的理解是正确的:在控制台应用程序中,默认情况下,由于默认的同步上下文,续体将被计划到线程池中。每个异步方法都会同步启动,因此您的for循环将在同一线程上执行DoOpAsync的开头。假设SomeOperationAsync返回一个未完成的任务,则续体将在线程池中计划。所以每个DoOpAsync调用可能会并行继续进行。

感谢 Stephen 的澄清 :) - darkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接