c# - Parallel.ForEach 中的嵌套异步方法
问题描述
我有一个在其中运行多个异步方法的方法。我必须遍历设备列表,并将设备传递给此方法。我注意到这需要很长时间才能完成,所以我正在考虑使用它,Parallel.ForEach
以便它可以同时针对多个设备运行此过程。
假设这是我的方法。
public async Task ProcessDevice(Device device) {
var dev = await _deviceService.LookupDeviceIndbAsNoTracking(device);
var result = await DoSomething(dev);
await DoSomething2(dev);
}
然后 DoSomething2 也调用了一个异步方法。
public async Task DoSomething2(Device dev) {
foreach(var obj in dev.Objects) {
await DoSomething3(obj);
}
}
随着时间的推移,设备列表不断变大,因此该列表增长得越多,程序完成ProcessDevice()
对每个设备运行所需的时间就越长。我想一次处理多个设备。所以我一直在研究使用Parallel.ForEach
.
Parallel.ForEach(devices, async device => {
try {
await ProcessDevice(device);
} catch (Exception ex) {
throw ex;
}
})
似乎该程序在设备完全处理之前完成。我也尝试过创建一个任务列表,然后为每个设备添加一个运行 ProcessDevice 的新任务到该列表中,然后等待 Task.WhenAll(listOfTasks);
var listOfTasks = new List<Task>();
foreach(var device in devices) {
var task = Task.Run(async () => await ProcessDevice(device));
listOfTasks.Add(task);
}
await Task.WhenAll(listOfTasks);
但似乎该任务被标记为完成之前ProcessDevice()
实际上是完成运行。
请原谅我对这个问题的无知,因为我是并行处理的新手,不知道发生了什么。是什么导致了这种行为,您是否可以提供任何文档来帮助我更好地理解该怎么做?
解决方案
你不能async
和Parallel.ForEach
. 由于您的底层操作是异步的,因此您希望使用异步并发,而不是并行。异步并发最容易表达为WhenAll
:
var listOfTasks = devices.Select(ProcessDevice).ToList();
await Task.WhenAll(listOfTasks);
推荐阅读
- php - 部署到 Heroku 时安装依赖项时出错
- codenameone - 代号一android在firebase上注册推送通知失败,返回INVALID_PARAETERS错误字符串
- javascript - 如何访问子组件的方法?
- javascript - 使用jquery避免在同一个表中重复数据
- python - 如何在 Django 1.11 的 Detailview 中添加类似的帖子
- java - 从活动移动到上一个片段
- c# - 与给定 SQL 查询等效的 LINQ MVC 查询是什么?
- python - 基于数值有条件地创建数据框列
- java - java.lang.NoClassDefFoundError - org/apache/spark/sql/hive/HiveContext
- apache-spark - 如何使用 array_remove Spark SQL 内置函数删除空值