Prashanth
Prashanth

Reputation: 71

How to combine the results of multiple async calls

public async Task<List<string>> getAllQueries()
{ 
   List<string> allQueries = new List<string>();
   for (int i =0 ; i < 10; i++)
   {
      List<string> queries = await getQueriesForId(i);
      allQueries.AddRange(queries);
   }  
   return allQueries;
}

Is there anything wrong with this code. I am not getting the correct results. I have not much idea about async/await. I observed that this function is returning the list without combining the results from all concurrent calls. Could somebody please let me know how to combine the lists coming from all concurrent calls and then only return ?

Upvotes: 6

Views: 7026

Answers (2)

ermish
ermish

Reputation: 1270

I would recommend using Task.WhenAll(). I created these handy extension methods you might find useful:

public static Task<TResult[]> SelectAsync<T, TResult>(
    this IEnumerable<T> list, 
         Func<T, Task<TResult>> functionToPerform)
{
    var tasks = list.Select(functionToPerform.Invoke);
    return Task.WhenAll(tasks);
}

And here's an example how to use it:

var results = await myItems.SelectAsync(item => DoStuff(item)).ConfigureAwait(false);

Upvotes: 2

David Pine
David Pine

Reputation: 24545

I would use the Task.WhenAll method and combine the results once they have all be materialized, consider the following:

public async Task<List<string>> GetAllQueriesAsync()
{ 
   var tasks = 
       Enumerable.Range(0, 10)
                 .Select(i => GetQueriesForIdAsync(i));

   await Task.WhenAll(tasks);
   return tasks.SelectMany(t => t.Result).ToList();
}

With the following snippet there are several key changes that I made.

  1. Suffix Task and Task<T> returning methods with "Async"
  2. Utilized Enumerable.Range instead of for loop
    • This will return a list of IEnumerable<Task<List<string>>>
  3. Run all the queries in parallel

Upvotes: 3

Related Questions