【发布时间】:2020-10-07 03:51:09
【问题描述】:
我有一个 Parallel.ForEach 循环,它遍历一个集合。在循环内部,我进行了多次网络 I/O 调用。我使用了 Task.ContinueWith 并嵌套了随后的 async-await 调用。处理的顺序无关紧要,但来自每个异步调用的数据应该以同步的方式处理。含义 - 对于每次迭代,从第一个异步调用检索到的数据应该传递给第二个异步调用。第二个异步调用完成后,两个异步调用的数据应该一起处理。
Parallel.ForEach(someCollection, parallelOptions, async (item, state) =>
{
Task<Country> countryTask = Task.Run(() => GetCountry(item.ID));
//this is my first async call
await countryTask.ContinueWith((countryData) =>
{
countries.Add(countryData.Result);
Task<State> stateTask = Task.Run(() => GetState(countryData.Result.CountryID));
//based on the data I receive in 'stateTask', I make another async call
stateTask.ContinueWith((stateData) =>
{
states.Add(stateData.Result);
// use data from both the async calls pass it to below function for some calculation
// in a synchronized way (for a country, its corresponding state should be passed)
myCollection.ConcurrentAddRange(SomeCalculation(countryData.Result, stateData.Result));
});
});
});
我在没有使用 continue await 的情况下尝试了上述方法,但它没有以同步方式工作。现在,上面的代码执行完毕,但没有记录被处理。
请问有什么帮助吗?让我知道是否可以添加更多详细信息。
【问题讨论】:
-
在同一个代码中混合
await和ContinueWith似乎非常奇怪,并且:如果您已经在 TP 上,使用Task.Run很奇怪。 ..看看重构它,但是...这不仅仅是有点奇怪! -
@MarcGravell:你可能是对的。我的意图是并行处理发生多个网络 I/O 调用的数据,但以同步方式。
-
作为一般规则,你不应该使用
ContinueWith... 几乎永远不要再使用了 -
Parallel.ForEachis not async-friendly。传递的 lambda 是 async void。该方法将在启动异步操作后立即完成,MaxDegreeOfParallelism选项将不被尊重......很多讨厌的问题。仅将此方法用于 CPU 密集型工作。
标签: c# asynchronous async-await task-parallel-library parallel.foreach