Await for list of Tasks

48,134

Solution 1

You are looking for Task.WaitAll (assuming your TaskList implemented IEnumerable<Task>)

Task.WaitAll(TaskList.ToArray());

Edit: Since WaitAll only takes an array of task (or a list of Task in the form of a variable argument array), you have to convert your Enumerable. If you want an extension method, you can do something like this:

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

TaskList.WaitAll();

But that's really only syntactic sugar.

Solution 2

You are looking for 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);
Share:
48,134
ctlaltdefeat
Author by

ctlaltdefeat

Updated on October 19, 2020

Comments

  • ctlaltdefeat
    ctlaltdefeat over 3 years

    I'm trying to do something like this:

    foreach (var o in ObjectList) 
    { 
        CalculateIfNeedToMakeTaskForO(o);
    
        if (yes) 
            TaskList.Add(OTaskAsync());
    }
    

    Now I would like to wait for all these tasks to complete. Besides doing

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

    Is there anything I could do? (better, more elegant, more "correct")

  • ctlaltdefeat
    ctlaltdefeat almost 11 years
    Thanks, but I've edited my question slightly to correspond to my code. My problem is to record the results as well, and not just to wait for them to finish. I guess in this case there is no choice but to loop with await?
  • Simon Belanger
    Simon Belanger almost 11 years
    @ctlaltdefeat Well, yes. However, you can use LINQ to project the enumerable. I'll edit to explain.
  • ctlaltdefeat
    ctlaltdefeat almost 11 years
    Thanks, but I don't quite understand LINQ or IEnumerable stuff anyway :D I just write stuff that looks like it should be enumerable, and usually it is
  • ctlaltdefeat
    ctlaltdefeat almost 11 years
    Hey, some of your posts helped me get started with async and await, but turns out I'm not needing to use any of their functionality so far!
  • Simon Belanger
    Simon Belanger almost 11 years
    @ctlaltdefeat I understand. Linq is a good tool to have when you work with collections
  • ctlaltdefeat
    ctlaltdefeat almost 11 years
    Just to make sure though: the way I've written the first part (creating the task list), do the OtaskAsyncs start immediately, or after the entire first foreach has finished? My goal is for them to start as soon as we know we need a task for it, before we've calculated whether the other ones need a task.
  • Simon Belanger
    Simon Belanger almost 11 years
    @ctlaltdefeat I'm guessing you are returning from OTaskAsync with Task.Factory.StartNew or a variant. If it is, then yes, the task start immediately.
  • ctlaltdefeat
    ctlaltdefeat almost 11 years
    Similar question as I posed above: the way you've written it, it seems nothing happens until we know which objects in the ObjectList need a task for them, and which don't. My aim is for the task for the first object (assuming it needs one) to start as soon as we calculate we need it, before we calculate if the second element needs it.
  • ctlaltdefeat
    ctlaltdefeat almost 11 years
    I'm not sure I understand. Each task is basically "await ResultOfSomeHTTPCallAsync(O)"
  • rony l
    rony l over 9 years
    This is the better answer since it asynchronously awaits the result. calling Task.WaitAll blocks the calling thread until all tasks are completed
  • user3156301
    user3156301 almost 9 years
    "Task<T>.Result will implicitly await" is not true. It will block the thread, not await, and will be a potential cause of deadlocks. See this explanation, and instead use await Task.WhenAll as per Stephen Cleary's answer.
  • Simon Belanger
    Simon Belanger almost 9 years
    @JoeDaley Good read, thank you. I'll remove the second part of the answer.