2016-07-20 38 views
-2

使用Task.WhenAll有很多好处,但它至少使写入内容所需的LOC增加一倍。Task.WhenAll使用较少的代码行

清单1

var result1 = await SomeLongRunningOperation1().ConfigureAwait(false); 
var result2 = await SomeLongRunningOperation2().ConfigureAwait(false); 
var result3 = await SomeLongRunningOperation3().ConfigureAwait(false); 

Listing2

var result1Task = SomeLongRunningOperation1(); 
var result2Task = SomeLongRunningOperation2(); 
var result3Task = SomeLongRunningOperation3(); 

await Task.WhenAll(
    result1Task, 
    result2Task, 
    result3Task) 
    .ConfigureAwait(false); 

var result1 = result1Task.Result; 
var result2 = result2Task.Result; 
var result3 = result3Task.Result; 

显然清单1等待3个操作彼此(3×10秒= 30秒)后,而Listing2等待3个操作中的同一时间(全部3秒只有10秒)。

但是清单2中的代码更难以阅读。

我的问题是: 是否有可能将清单2的逻辑编写成易于阅读且与清单1一样简短的内容?

+0

PUT“result1Task result2Task result3Task”的数组,你的代码更短。 –

回答

1

正如我在评论说,这实现了您正在寻找的并行性,并使用更少的代码比清单2:

var result1Task = SomeLongRunningOperation1(); 
var result2Task = SomeLongRunningOperation2(); 
var result3Task = SomeLongRunningOperation3(); 

var result1 = await result1Task.ConfigureAwait(false); 
var result2 = await result2Task.ConfigureAwait(false); 
var result3 = await result3Task.ConfigureAwait(false); 

它确实有细微差别的时机 - 如果result1可用显著在result2result3可用之前,它将被更早地分配。但是,由于你所有3个任务(并且对结果都没有做任何事情),在完成所有三项任务之前,实际上你不会继续完成result3的任务 - 正是你所要求的WhenAll

0

您可以使用Tuple s,但您必须为各种arities构造辅助方法。这里有这样一个为3个参数:

public static async Task<Tuple<T1, T2, T3>> WhenAll<T1, T2, T3>(Task<T1> t1, Task<T2> t2, Task<T3> t3) 
{ 
    await Task.WhenAll(t1, t2, t3).ConfigureAwait(false); 
    var result1 = await t1.ConfigureAwait(false); 
    var result2 = await t2.ConfigureAwait(false); 
    var result3 = await t3.ConfigureAwait(false); 
    return Tuple.Create(result1, result2, result3); 
} 

用法:

var results = await WhenAll(Operation1(), Operation2(), Operation3()); 
var result1 = results.Item1; 

在C#7,你可以使用内置的元组支持,这样的元组的项目将被命名。

0

如果您的操作都具有相同的结果类型,你也可以这样做:

var task1 = SomeLongRunningOperation1(); 
var task2 = SomeLongRunningOperation2(); 
var task3 = SomeLongRunningOperation3(); 

var results = await Task.WhenAll(task1, task2, task3).ConfigureAwait(false);