如何构建下面的代码以便调用异步方法?如何正确使用异步方法编写Parallel.For
Parallel.For(0, elevations.Count(), delegate(int i)
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
如何构建下面的代码以便调用异步方法?如何正确使用异步方法编写Parallel.For
Parallel.For(0, elevations.Count(), delegate(int i)
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
Parallel.For()
不async
方法很好地工作。如果您不需要限制并行度(即您可以同时执行所有任务),则可以简单地启动所有的Task
,然后等待它们完成:
var tasks = Enumerable.Range(0, elevations.Count())
.Select(i => BuildSheetsAsync(userID, elevations[i], includeLabels));
List<Bitmap> allSheets = (await Task.WhenAll(tasks)).SelectMany(x => x).ToList();
我无法添加它要求IEnnumerable的List
@ AlumCloud.Com啊,我没有注意到'BuildSheetsAsync()'已经返回一个集合。如果你想从一个集合集合中创建一个集合,你可以使用'SelectMany()'。并且要从'IEnumerable'集合中创建一个列表,使用'ToList()'。 – svick
宾果!非常感谢。 –
我建议你看看这个问题,我问前几天,结束行动回答我,基本上我一直在寻找一个并行和异步的ForEach方法。
该方法使用SemaphoreSlim
来并行处理事物,它接受异步方法作为输入操作。
您可能还想看看我在答复结束时提供的两个链接,它们对于实现此类行为非常有帮助,而且它们还包含使用Partitioner
代替的另一种方法。
就我个人而言,我不喜欢Parallel.For
,因为它是一个同步调用,如我在给出的链接中所解释的;我想这一切“异步” :-)
+1,除了'SemaphoreSlim'显然不是必需的OP的情况。我也可以建议在代码中使用具有超时的'CancellationTokenSource'而不是'Timer'对象。 – Noseratio
调用里面Parallel.For
您的异步方法最简单的方法是下一个:
Parallel.For(0, elevations.Count(), async i =>
{
allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels));
});
==============
MarioDS提到的评论绝对正确的,在这种情况下你可能有没有观察到的例外。这绝对是非常重要的事情,您应该始终考虑与异步代表达成协议。
在这种情况下,如果您认为您会有例外情况,则可以在代表内使用try/catch
块。或者在某些情况下,如果您的情况良好,您可以订阅TaskScheduler.UnobservedTaskException活动。
这会导致错误。异步委托返回“Task”,而Parallel构造不会等待该任务。这意味着异常是不可见的,你不能确定在“并行”之后。因为调用已经证明所有的工作都已经完成了(你也不能轻易验证)。 – MarioDS
[Parallel.ForEach中嵌套等待]的可能的重复(https://stackoverflow.com/questions/11564506/nesting-await-in-parallel-foreach) –