并发执行异步方法

时间:2014-03-01 17:00:11

标签: c# async-await

使用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个调用将彼此同步执行。我如何让它们同时执行并在结果完成时加入结果?

3 个答案:

答案 0 :(得分:10)

  

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

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

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失败 - 因为您的异步方法将传播等待task2之前task3的例外情况。

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

答案 1 :(得分:0)

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

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

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

new_dict = {}

for q in query:
    q['children'] = []
    q['parent'] = 1
    new_dict[q['id']] = q

for k, v in new_dict.iteritems():
    p_id = v['parent_id']
    for kk, vv in new_dict.iteritems():
        if kk == p_id:
            v['parent'] = 0
            vv['children'].append(v)

results = []

for d_id, d_item in new_dict.iteritems():
    if d_item['parent'] == 1:
        results.append(d_item)

print results

答案 2 :(得分:-1)

您可以使用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