2013-10-09 45 views
12

如何构建下面的代码以便调用异步方法?如何正确使用异步方法编写Parallel.For

Parallel.For(0, elevations.Count(), delegate(int i) 
{ 
    allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels)); 
}); 
+0

[Parallel.ForEach中嵌套等待]的可能的重复(https://stackoverflow.com/questions/11564506/nesting-await-in-parallel-foreach) –

回答

22

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(); 
+0

我无法添加它要求IEnnumerable的List 的集合。我如何做到这一点? var task = Enumerable.Range(0,elevations.Length).Select(i => BuildSheetsAsync(userID,elevation [i],includeLabels)); 列表 allSheets =新列表(); allSheets.AddRange(等待Task.WhenAll(任务));发生错误时,我allSheets.AddRange(等待Task.WhenAll(任务)); –

+0

@ AlumCloud.Com啊,我没有注意到'BuildSheetsAsync()'已经返回一个集合。如果你想从一个集合集合中创建一个集合,你可以使用'SelectMany()'。并且要从'IEnumerable'集合中创建一个列表,使用'ToList()'。 – svick

+0

宾果!非常感谢。 –

4

我建议你看看这个问题,我问前几天,结束行动回答我,基本上我一直在寻找一个并行和异步的ForEach方法

该方法使用SemaphoreSlim来并行处理事物,它接受异步方法作为输入操作。

您可能还想看看我在答复结束时提供的两个链接,它们对于实现此类行为非常有帮助,而且它们还包含使用Partitioner代替的另一种方法。

就我个人而言,我不喜欢Parallel.For,因为它是一个同步调用,如我在给出的链接中所解释的;我想这一切“异步” :-)

这就是:Asynchronously and parallelly downloading files

+1

+1,除了'SemaphoreSlim'显然不是必需的OP的情况。我也可以建议在代码中使用具有超时的'CancellationTokenSource'而不是'Timer'对象。 – Noseratio

2

调用里面Parallel.For您的异步方法最简单的方法是下一个:

Parallel.For(0, elevations.Count(), async i => 
{ 
    allSheets.AddRange(await BuildSheetsAsync(userID, elevations[i], includeLabels)); 
}); 

==============

MarioDS提到的评论绝对正确的,在这种情况下你可能有没有观察到的例外。这绝对是非常重要的事情,您应该始终考虑与异步代表达成协议。

在这种情况下,如果您认为您会有例外情况,则可以在代表内使用try/catch块。或者在某些情况下,如果您的情况良好,您可以订阅TaskScheduler.UnobservedTaskException活动。

+1

这会导致错误。异步委托返回“Task”,而Parallel构造不会等待该任务。这意味着异常是不可见的,你不能确定在“并行”之后。因为调用已经证明所有的工作都已经完成了(你也不能轻易验证)。 – MarioDS

相关问题