private void RunWaitForTasksToCompleteOneByOne() { // this is a good pattern to use when: // - You are wanting to handle (retry, log error, discard) failed tasks as they happen. // - when you want to overlapp computation with result processing int numberOfTasksToRun = 5; List <Task <string> > listOfTasks = new List <Task <string> >(); SimpleAsyncClass2 SAC2 = new SimpleAsyncClass2(); for (int index = 0; index < numberOfTasksToRun; index++) { if (index % 2 == 0) { listOfTasks.Add(SAC2.AsyncMethod1()); } else { listOfTasks.Add(SAC2.AsyncMethod2()); } } while (listOfTasks.Count > 0) { int completedTaskIndex = Task.WaitAny(listOfTasks.ToArray()); // log errors, retry, skip and move on, etc code here Console.WriteLine(listOfTasks[completedTaskIndex].Result); listOfTasks.RemoveAt(completedTaskIndex); } Console.WriteLine("All tasks complete"); }