Search code examples
c#asynchronoustask.net-6.0.net-7.0

Process async tasks of different result types as they complete


I am trying to process each async task result when/as they complete. These tasks have different result sets. I like to execute these tasks concurrently but need to process the result when any finishes.

There are many google search results when async functions have the same return type, however, I couldn't get my hand to one with different result sets.

private async Task CompleteTasksAsync()
{
    var taskA = GetStringAsync();
    var taskB = GetIntAsync();
    var taskC = GetStringListAsync();
    var taskD = GetGenericAsync<double>(1d);

    //var tasks = new[] {taskA, taskB, taskC, taskD} // this will only work if all
                                                     // tasks have same return type

    await Task.WhenAll(taskA, taskB, taskC, taskD); // This statement will wait
                                                    // until all tasks are completed

    // when Task A finished Console.WriteLine(taskA.Result);
    // when Task B finished Console.WriteLine(taskB.Result);
    // when Task C finished Console.WriteLine(taskC.Result);
    // when Task D finished Console.WriteLine(taskD.Result);
}

private Task<string> GetStringAsync() => Task.FromResult("string");
private Task<int> GetIntAsync() => Task.FromResult(1);
private Task<List<string>> GetStringListAsync()
    => Task.FromResult(new List<string> { "string"});
private Task<T> GetGenericAsync<T>(T data) => Task.FromResult(data);

Solution

  • Finally, For anyone who want to do it without the if/switch. I used Dictionary<TAsk, Action> and this helped me to shape the tasks and results.

    private async Task CompleteTasksAsync()
    {
       var taskA = GetStringAsync();
       var taskB = GetIntAsync();
       var taskC = GetStringListAsync();
       var taskD = GetGenericAsync<double>(1d);
    
       Dictionary<Task, Action> tasks = new()
       {
         {taskA, () => Console.WriteLine(taskA.Result)},
         {taskB, () => Console.WriteLine(taskB.Result)  },       {taskC, () => Console.WriteLine(taskC.Result) },
         {taskD, () => Console.WriteLine(taskD.Result) }
       };
    
       while (tasks.Any())
       {
          var completedTask = await Task.WhenAny(tasks.Keys);
    
          tasks[completedTask]();
    
          tasks.Remove(completedTask);
      }
    
    }