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