并发执行异步方法

使用async / await模型,我有一个方法,它对Web服务进行3次不同的调用,然后返回结果的并集。

var result1 = await myService.GetData(source1); var result2 = await myService.GetData(source2); var result3 = await myService.GetData(source3); allResults = Union(result1, result2, result3); 

使用典型等待,这3个调用将彼此同步执行。 我将如何让它们同时执行并在完成后加入结果?

我将如何让它们并行执行并在结果完成时加入结果?

最简单的方法是创建所有任务然后等待它们:

 var task1 = myService.GetData(source1); var task2 = myService.GetData(source2); var task3 = myService.GetData(source3); // Now everything's started, we can await them var result1 = await task1; var result1 = await task2; var result1 = await task3; 

你也可以考虑Task.WhenAll 。 你需要考虑多个任务失败的可能性……使用上面的代码你不会看到task3的失败,例如,如果task2失败 – 因为你的async方法会在你等待task3之前传播来自task2的exception。

我不是在这里建议一个特定的策略,因为它取决于你的具体情况。 您可能只关心成功/失败并记录一个失败原因,在这种情况下上面的代码很好。 否则,您可以将延续连接到原始任务以记录所有exception,例如。

作为一个更通用的解决方案,您可以使用我在下面编写的api,它还允许您定义最大并发异步请求数的实时限制机制。

inputEnumerable将是您的源的可枚举,asyncProcessor是您的异步​​委托(在您的示例中为myservice.GetData)。

如果asyncProcessor – myservice.GetData – 返回void或只是一个没有任何类型的Task,那么你可以简单地更新api来反映这一点。 (只需将所有Task <>替换为Task)

  public static async Task ForEachAsync( IEnumerable inputEnumerable, Func> asyncProcessor, int? maxDegreeOfParallelism = null) { IEnumerable> tasks; if (maxDegreeOfParallelism != null) { SemaphoreSlim throttler = new SemaphoreSlim(maxDegreeOfParallelism.Value, maxDegreeOfParallelism.Value); tasks = inputEnumerable.Select( async input => { await throttler.WaitAsync(); try { return await asyncProcessor(input).ConfigureAwait(false); } finally { throttler.Release(); } }); } else { tasks = inputEnumerable.Select(asyncProcessor); } await Task.WhenAll(tasks); } 

你可以使用Parallel类:

 Parallel.Invoke( () => result1 = myService.GetData(source1), () => result2 = myService.GetData(source2), () => result3 = myService.GetData(source3) ); 

有关更多信息,请访问: http : //msdn.microsoft.com/en-us/library/system.threading.tasks.parallel(v=vs.110).aspx