假设我想发出并行的API post请求。
在for循环中,我可以将http调用附加到任务列表中(每个任务使用Task.Run调用),然后等待所有任务使用await Task.WhenAll完成。因此,在等待网络请求完成时,控件将转到调用方。实际上,API请求将并行进行。
类似地,我可以使用Parallel.ForEachAsync,它将自动执行WhenAll并将控件返回给调用方。因此,我想问一下,ForEachAsync是否是对普通循环列表(异步等待Task.Run)和WhenAll的替代。
发布于 2021-07-29 19:29:26
不,与使用Parallel.ForEachAsync API相比,Task.WhenAll API有相当大的差异:
await Task.WhenAll返回一个数组,其中包含异步操作的结果。相反,Parallel.ForEachAsync返回一个裸露的Task。如果您想要得到结果,您必须依赖副作用,比如作为异步操作的一部分更新ConcurrentQueue<T>。Parallel.ForEachAsync在ThreadPool线程(可配置)上并行调用所提供的异步委托。相反,使用Task.WhenAll的常见模式是在当前线程上依次创建Task。这引起了对在Parallel.ForEachAsync应用程序中使用ASP.NET应用程序的关注,在该应用程序中,ThreadPool上的卸载工作可能有可伸缩性含义。Parallel.ForEachAsync调用异步委托并等待生成的任务,同时强制执行等于Environment.ProcessorCount的最大并发级别。此行为可通过MaxDegreeOfParallelism选项进行配置。相反,使用Task.WhenAll的常见模式是一次性创建所有任务,不限制并发性。Task.WhenAll的常见模式是假设创建所有任务是不可能中途失败的,因此对此不采取任何预防措施。如果真的发生这种情况,火灾和遗忘的任务可能会被泄露。这在Parallel.ForEachAsync API中是不可能的。Task上发生第一个错误,Task将停止调用异步委托,然后在等待所有已创建的任务之后传播包含迄今发生的所有错误的失败。它还提供了一种机制,用于取消发生错误时正在运行的其他任务(在lambda中作为第二个参数传递的CancellationToken )。相反,Task.WhenAll总是等待所有任务的完成。这意味着,在最终接收包含所有失败任务的错误的AggregateException之前,您可能需要等待更长的时间。https://stackoverflow.com/questions/68544324
复制相似问题