通过等待每个任务异步转换IEnumerable <Task >

今天我想知道如何通过等待每个任务来转换任务列表。 请考虑以下示例:

private static void Main(string[] args) { try { Run(args); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); Console.ReadLine(); } } static async Task Run(string[] args) { //Version 1: does compile, but ugly and List overhead var tasks1 = GetTasks(); List gainStrings1 = new List(); foreach (Task task in tasks1) { gainStrings1.Add(await task); } Console.WriteLine(string.Join("", gainStrings1)); //Version 2: does not compile var tasks2 = GetTasks(); IEnumerable gainStrings2 = tasks2.Select(async t => await t); Console.WriteLine(string.Join("", gainStrings2)); } static IEnumerable<Task> GetTasks() { string[] messages = new[] { "Hello", " ", "async", " ", "World" }; for (int i = 0; i < messages.Length; i++) { TaskCompletionSource tcs = new TaskCompletionSource(); tcs.SetResult(messages[i]); yield return tcs.Task; } } 

我想在没有foreach的情况下转换我的任务列表,但是匿名函数语法和通常的函数语法都允许我做我的foreach所做的事情。

我是否必须依赖我的foreach和List或者有没有办法让它与IEnumerable及其所有优点一起使用?

那这个呢:

 await Task.WhenAll(tasks1); var gainStrings = tasks1.Select(t => t.Result).ToList(); 

等待所有任务结束,然后提取结果。 如果您不关心它们的完成顺序,这是理想的选择。

EDIT2:更好的方式:

 var gainStrings = await Task.WhenAll(tasks1);