2013-05-02 75 views
14

今天我想知道如何通過等待每個任務來轉換任務列表。 請看下面的例子:通過等待每個任務異步地轉換IEnumerable <Task<T>>

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<T> overhead 
    var tasks1 = GetTasks();      

    List<string> gainStrings1 = new List<string>(); 
    foreach (Task<string> task in tasks1) 
    { 
     gainStrings1.Add(await task); 
    } 
    Console.WriteLine(string.Join("", gainStrings1)); 

    //Version 2: does not compile 
    var tasks2 = GetTasks(); 
    IEnumerable<string> gainStrings2 = tasks2.Select(async t => await t); 
    Console.WriteLine(string.Join("", gainStrings2)); 
} 

static IEnumerable<Task<string>> GetTasks() 
{ 
    string[] messages = new[] { "Hello", " ", "async", " ", "World" }; 

    for (int i = 0; i < messages.Length; i++) 
    { 
     TaskCompletionSource<string> tcs = new TaskCompletionSource<string>(); 
     tcs.SetResult(messages[i]); 
     yield return tcs.Task; 
    } 
} 

我想改變我的任務列表,而無需在foreach,但無論是匿名函數的語法,也不是通常的功能語法允許我做我的foreach做什麼。

我必須依靠我的foreach和List<T>或有什麼辦法讓它與IEnumerable<T>及其所有的優點?

+0

爲什麼第二個不編譯?什麼是錯誤信息?如果在'Select'之後添加缺少的'ToList()',它會編譯嗎? – 2013-05-02 14:23:34

+1

它因爲它返回'IEnumerable >'。 – GameScripting 2013-05-02 14:25:52

回答

23

這個怎麼樣:

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

等待所有任務結束,然後提取結果。如果你不關心他們完成的順序,這是理想的。

EDIT2: 更好的方法:

var gainStrings = await Task.WhenAll(tasks1); 
+2

而不是'Select',你可以使用'WhenAll'的返回值,它將是每個任務所有結果的'string []'。 – Servy 2013-05-02 14:30:43

+0

根據這個:http://msdn.microsoft.com/en-us/library/hh194874.aspx只有當你給它一個數組時,它纔會這樣做。 – 2013-05-02 14:33:15

+3

您不需要'ToArray()','Task.WhenAll()'也適用於'IEnumerable >'。 – svick 2013-05-02 14:35:06

相關問題