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);
Author by
ctlaltdefeat
Updated on October 19, 2020Comments
-
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 almost 11 yearsThanks, 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 almost 11 years@ctlaltdefeat Well, yes. However, you can use LINQ to project the enumerable. I'll edit to explain.
-
ctlaltdefeat almost 11 yearsThanks, 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 almost 11 yearsHey, 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 almost 11 years@ctlaltdefeat I understand. Linq is a good tool to have when you work with collections
-
ctlaltdefeat almost 11 yearsJust 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 almost 11 years@ctlaltdefeat I'm guessing you are returning from
OTaskAsync
withTask.Factory.StartNew
or a variant. If it is, then yes, the task start immediately. -
ctlaltdefeat almost 11 yearsSimilar 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 almost 11 yearsI'm not sure I understand. Each task is basically "await ResultOfSomeHTTPCallAsync(O)"
-
rony l over 9 yearsThis is the better answer since it asynchronously awaits the result. calling Task.WaitAll blocks the calling thread until all tasks are completed
-
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 useawait Task.WhenAll
as per Stephen Cleary's answer. -
Simon Belanger almost 9 years@JoeDaley Good read, thank you. I'll remove the second part of the answer.