【问题标题】:Await for list of Tasks等待任务列表
【发布时间】:2013-07-11 09:25:31
【问题描述】:

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

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

    if (yes) 
        TaskList.Add(OTaskAsync());
}

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

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

有什么我可以做的吗? (更好、更优雅、更“正确”)

【问题讨论】:

    标签: c# .net task-parallel-library async-await


    【解决方案1】:

    您正在寻找Task.WaitAll(假设您的TaskList 实现了IEnumerable<Task>

    Task.WaitAll(TaskList.ToArray());
    

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

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

    但这实际上只是语法糖。

    【讨论】:

    • 谢谢,但我已经稍微编辑了我的问题以对应我的代码。我的问题是也要记录结果,而不仅仅是等待它们完成。我想在这种情况下别无选择,只能循环等待?
    • @ctlaltdefeat 好吧,是的。但是,您可以使用 LINQ 来投影可枚举。我会编辑解释。
    • 谢谢,但我还是不太了解 LINQ 或 IEnumerable 的东西 :D 我只是写一些看起来应该是可枚举的东西,而且通常是
    • @ctlaltdefeat 我明白了。当您使用集合时,Linq 是一个很好的工具
    • Task&lt;T&gt;.Result 将隐式等待”不正确。它将阻塞线程,而不是等待,并且将成为死锁的潜在原因。请参阅 this explanation,并根据 Stephen Cleary 的回答使用 await Task.WhenAll
    【解决方案2】:

    您正在寻找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);
    

    【讨论】:

    • 嘿,你的一些帖子帮助我开始使用 async 和 await,但事实证明,到目前为止我不需要使用它们的任何功能!
    • 我上面提出的类似问题:按照您编写它的方式,在我们知道 ObjectList 中的哪些对象需要为它们执行任务而哪些不需要之前,似乎什么都不会发生。我的目标是让第一个对象(假设它需要一个)的任务在我们计算出我们需要它时立即开始,然后再计算第二个元素是否需要它。
    • 这是更好的答案,因为它异步等待结果。调用 Task.WaitAll 会阻塞调用线程,直到所有任务都完成
    猜你喜欢
    • 1970-01-01
    • 2022-12-16
    • 2018-04-15
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 2011-12-13
    • 1970-01-01
    相关资源
    最近更新 更多