我无法理解为什么它似乎无法并行运行任务:
var tasks = new Task<MyReturnType>[mbis.Length];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = CAS.Service.GetAllRouterInterfaces(mbis[i], 3);
}
Parallel.ForEach(tasks, task => task.Start());
通过逐步执行,我发现这一行被评估后:
tasks[i] = CAS.Service.GetAllRouterInterfaces(mbis[i], 3);
任务开始。我想将所有新任务添加到列表中,然后并行执行它们。
最佳答案
如果GetAllRouterInterfaces
是async
方法,则结果Task
将已经启动(有关详细说明,请参见this answer)。
这意味着tasks
将包含多个任务,所有这些任务并行运行,而无需随后调用Parallel.ForEach
。
您可能希望等待tasks
中的所有条目完成,可以使用await Task.WhenAll(tasks);
进行此操作。
因此,您应该以:
var tasks = new Task<MyReturnType>[mbis.Length];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = CAS.Service.GetAllRouterInterfaces(mbis[i], 3);
}
await Task.WhenAll(tasks);
来自评论的更新
看来,尽管
GetAllRouterInterfaces
是async
并返回了Task
,但它仍在发出同步POST请求(大概在其他await
之前)。这可以解释为什么在发出此请求时,由于每次对GetAllRouterInterfaces
的调用都处于阻塞状态,所以您获得的并发性最低。理想的解决方案是发出异步POST请求,例如:await webclient.PostAsync(request).ConfigureAwait(false);
这将确保您的
for
循环不会被阻塞,并且请求是同时进行的。对话后进一步更新
看来您无法使POST请求成为异步请求,并且
GetAllRouterInterfaces
实际上并未执行任何异步工作,因此,我建议以下建议:从
async
删除GetAllRouterInterfaces
并将返回类型更改为MyReturnType
像这样并行调用
GetAllRouterInterfaces
var routerInterfaces = mbis.AsParallel()
.Select(mbi => CAS.Service.GetAllRouterInterfaces(mbi, 3));