使用 async/await 并行执行任务继续
Posted
技术标签:
【中文标题】使用 async/await 并行执行任务继续【英文标题】:Task continuation parallel execution with async/await 【发布时间】:2013-01-22 16:45:40 【问题描述】:在使用 async/await 构造的 console 应用程序的上下文中,我想知道“延续”是否可以在多个并行运行不同 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 完成端口异步发送一些请求,因此根本不会阻塞任何线程。
现在,如果我调用将发出 1000 个异步操作的 Start 方法,那么异步方法的延续代码(在等待之后)是否可以在不同的 CPU 线程上并行运行?即在这种情况下我是否需要处理线程同步并同步对字段“i”的访问?
【问题讨论】:
您是否希望它们并行运行?如果你这样做了,同步所有调用就很容易了,只需await DoOpAsync
in Start
。
【参考方案1】:
是的,您应该在i++
周围放置线程同步逻辑,因为在await
之后可能会有多个线程同时执行代码。
由于您的 for 循环,将创建多个任务。这些任务将在不同的线程池线程上执行。一旦这些任务完成,延续,即等待之后的代码,将在不同的线程池线程上再次执行。这使得多个线程可以同时执行 i++
【讨论】:
感谢您的回答哈里斯!【参考方案2】:您的理解是正确的:在控制台应用程序中,由于默认SynchronizationContext
,默认情况下延续将被调度到线程池。
每个async
方法都会同步启动,因此您的for
循环将在同一线程上执行DoOpAsync
的开头。假设SomeOperationAsync
返回一个不完整的Task
,则将在线程池上安排延续。
因此DoOpAsync
的每个调用都可以并行继续。
【讨论】:
感谢斯蒂芬澄清:)以上是关于使用 async/await 并行执行任务继续的主要内容,如果未能解决你的问题,请参考以下文章
javascript async / await - 并行处理数组