等待任务列表

ctl*_*eat 32 .net c# task-parallel-library async-await

我正在尝试做这样的事情:

foreach (var o in ObjectList) 
{ 
    CalculateIfNeedToMakeTaskForO(o);

    if (yes) 
        TaskList.Add(OTaskAsync());
}
Run Code Online (Sandbox Code Playgroud)

现在我想等待所有这些任务完成.除了做

foreach(var o in ObjectList)
{
    Result.Add("result for O is: "+await OTaskAsync());
}
Run Code Online (Sandbox Code Playgroud)

有什么我能做的吗?(更好,更优雅,更"正确")

Ste*_*ary 94

您正在寻找Task.WhenAll:

var tasks = ObjectList
    .Where(o => CalculateIfNeedToMakeTaskForO(o))
    .Select(o => OTaskAsync(o))
    .ToArray();
var results = await Task.WhenAll(tasks);
var combinedResults = results.Select(r => "result for O is: " + r);
Run Code Online (Sandbox Code Playgroud)

  • 这是更好的答案,因为它异步等待结果.调用Task.WaitAll会阻塞调用线程,直到完成所有任务 (22认同)

Sim*_*ger 34

您正在寻找Task.WaitAll(假设您已TaskList实施IEnumerable<Task>)

Task.WaitAll(TaskList.ToArray());
Run Code Online (Sandbox Code Playgroud)

编辑:由于WaitAll只接受一个任务数组(或Task一个变量参数数组形式的列表),您必须转换您的Enumerable.如果你想要一个扩展方法,你可以这样做:

public static void WaitAll(this IEnumerable<Task> tasks) 
{
    Task.WaitAll(tasks.ToArray());
}      

TaskList.WaitAll();
Run Code Online (Sandbox Code Playgroud)

但那真的只是语法糖.

  • "`任务<T> .Result`将隐含地等待"不是真的.它将阻塞线程,而不是等待,并将成为死锁的潜在原因.请参阅[此解释](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html),然后根据Stephen Cleary的回答使用`await Task.WhenAll`. (10认同)