【发布时间】:2016-09-30 14:59:14
【问题描述】:
我已经为一些项目切换到 .net Core,但现在遇到了 Parallel.ForEach 的问题。过去,我经常有一个 id 值列表,然后我会使用它来发出 Web 请求以获取完整数据。它看起来像这样:
Parallel.ForEach(myList, l =>
{
// make web request using l.id
// process the data somehow
});
嗯,在 .net Core 中,Web 请求必须全部标记为 await,这意味着 Parallel.ForEach 操作必须标记为 async。但是,将 Parallel.ForEach 操作标记为 async 意味着我们有一个导致问题的 void async 方法。在我的特殊情况下,这意味着响应返回到应用程序在并行循环中的所有 Web 请求都完成之前,这既尴尬又会导致错误。
问题:在此处使用 Parallel.ForEach 的替代方法是什么?
我发现的一个可能的解决方案是将并行循环包装在任务中并等待任务:
await Task.Run(() => Parallel.ForEach(myList, l =>
{
// stuff here
}));
(在这里找到:Parallel.ForEach vs Task.Run and Task.WhenAll)
但是,这对我不起作用。当我使用它时,我仍然会在循环完成之前返回应用程序。
另一种选择:
var tasks = new List<Task>();
foreach (var l in myList)
{
tasks.Add(Task.Run(async () =>
{
// stuff here
}));
}
await Task.WhenAll(tasks);
这似乎可行,但这是唯一的选择吗?似乎新的 .net Core 使 Parallel.ForEach 几乎无用(至少在嵌套 Web 调用方面)。
感谢任何帮助/建议。
【问题讨论】:
-
async/await设计用于长时间阻塞I/O 操作,而Parallel设计用于长时间阻塞CPU 操作。如果您发现自己试图在Parallel函数体中编写异步代码,那么您做错了什么。考虑改用Task.WhenAll。 -
除了上面的评论,当你做Task.Run(async() => ...),你也几乎总是做错事。
-
您应该查看TPL Dataflow。让你的生活轻松很多。它不是 .NET Framework 的一部分,但您可以使用 nuget 来获取它,
-
@MatiasCicero 感谢您解释预期用途之间的差异,这非常有启发性。
-
@Evk 如果那是错误的方式,你能指出正确的方向吗?