1
votes

I need to run multiple awaitable tasks, and then gather their results into a list and return it.

I can create the tasks in a loop and use Task.WhenAll to await them, but I can't figure out how to access the results of each awaited task. I tried the below but Result is not defined.

    List<Service> services = new List<Service>();
    List<Exception> exceptions = new List<Exception>();
    List<Task<Service>> tasks = new List<Task<Service>>();

    foreach (string serviceMoniker in monikers)
    {
      try
      {
        tasks.Add(GetService(serviceMoniker, tenantMoniker, countryCode, environmentId));
      }
      catch (Exception e) { exceptions.Add(e); }
    }

    var continuation = Task.WhenAll(tasks);

    for (int i=0; i < continuation.Result.Length - 1; i++)
    {
      services.Add(continuation.Result[i].Result);
    }

another attempt

    await Task.WhenAll(tasks);

    foreach (Task t in tasks)
    {
      services.Add(t.Result);
    }
2
when you await the the task.whenall you will get all the results in an array. - Nkosi
I believe you're checking for exceptions in the wrong place: you won't see an exception when calling tasks.Add(…), but what you will see is that some of the tasks are faulted as an unhandled exception was thrown. - stuartd
Using the await keyword is generally better than blocking by accessing .Result: Services[] services = await Task.WhenAll(tasks); - stannius
@stannius nothing was blocking (at least not in the second attempt shown). I just did the loop wrong. - ztorstri

2 Answers

1
votes

You are iterating (on the foreach) to a Task variable (which doesn't have a typed Result), you need to iterate to a Task<Service> variable (or use var, since your tasks list is already typed), that is:

foreach (var t in tasks)
{
  services.Add(t.Result);
}
0
votes

I was missing the generic part of the Task in the loop. Changed this

await Task.WhenAll(tasks);

foreach (Task t in tasks)
{
  services.Add(t.Result);
}

to this

await Task.WhenAll(tasks);

foreach (Task<Service> t in tasks)
{
  services.Add(t.Result);
}

and now it works