I have to consume the output of multiple asynchronous tasks right after they complete.
Would there be a reasonable perf difference in any of these approaches?
Simple Await
public async Task<List<Baz>> MyFunctionAsync(List<Foo> FooList) {
results = new List<Baz>();
List<Task<List<Baz>>> tasks = new List<Task<List<Baz>>>();
foreach (Foo foo in FooList) {
tasks.Add(FetchBazListFromFoo(entry));
foreach (Task<List<Baz>> task in tasks) {
results.AddRange(await task);
return results;
}
WhenAll
public async Task<List<Baz>> MyFunctionAsync(List<Foo> FooList) {
results = new List<Baz>();
List<Task<List<Baz>>> tasks = new List<Task<List<Baz>>>();
foreach (Foo foo in FooList) {
tasks.Add(FetchBazListFromFoo(entry));
foreach (List<Baz> bazList in await Task.WhenAll(tasks))
results.AddRange(bazList);
return results;
}
WaitAll
public async Task<List<Baz>> MyFunctionAsync(List<Foo> FooList) {
results = new List<Baz>();
List<Task<List<Baz>>> tasks = new List<Task<List<Baz>>>();
foreach (Foo foo in FooList) {
tasks.Add(FetchBazListFromFoo(entry));
foreach (List<Baz> bazList in await Task.WaitAll(tasks))
results.AddRange(bazList);
return results;
}
WhenAny
public async Task<List<Baz>> MyFunctionAsync(List<Foo> FooList) {
results = new List<Baz>();
List<Task<List<Baz>>> tasks = new List<Task<List<Baz>>>();
foreach (Foo foo in FooList) {
tasks.Add(FetchBazListFromFoo(entry));
while (tasks.Count > 0) {
Task<List<Baz>> finished = Task.WhenAny(tasks);
results.AddRange(await finished);
tasks.Remove(finished);
}
return results;
}
FooListhas about 100 entries.FetchBazListFromFoomakes about 30 REST API calls and does some synchronous work for each result of REST API call.
Additionally, Is there an internal overhead diff in WhenAll v WhenAny?
WhenAll returns control after all tasks are completed, while WhenAny returns control as soon as a single task is completed. The latter seems to require more internal management.
The simple await will perform each item one after another, essentially synchronously - this would be the slowest.
WhenAllwill wait for all of tasks to be done - the runtime will be whatever the longest single task is.Do not use
WaitAll- it is synchronous, just useWhenAllWhenAnyallows you to handle each task as it completes. This in will be faster thanWhenAllin some cases, depending on how much processing you have to do after the task.IMO, unless you need to start post processing immediately when each task complets,
WhenAllis the simplest/cleanest approach and would work fine in most scenarios.