3

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);
    }
ztorstri
  • 369
  • 6
  • 12
  • 2
    when you await the the task.whenall you will get all the results in an array. – Nkosi May 20 '19 at 15:49
  • 1
    Possible duplicate of [Awaiting multiple Tasks with different results](https://stackoverflow.com/questions/17197699/awaiting-multiple-tasks-with-different-results) – 500 - Internal Server Error May 20 '19 at 15:50
  • 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](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.isfaulted?view=netframework-4.8) as an unhandled exception was thrown. – stuartd May 20 '19 at 15:50
  • Using the await keyword is generally better than blocking by accessing .Result: Services[] services = await Task.WhenAll(tasks); – stannius May 20 '19 at 15:52
  • @stannius nothing was blocking (at least not in the second attempt shown). I just did the loop wrong. – ztorstri May 20 '19 at 15:56

2 Answers2

4

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

ztorstri
  • 369
  • 6
  • 12
4

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);
}
Jcl
  • 27,696
  • 5
  • 61
  • 92