2013-05-02 8 views
14

今日、タスクのリストをそれぞれ待って変換する方法を知りました。Transform 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>とそのすべての利点を利用するための方法がありますか?すべてのタスクが終了してから結果を抽出する

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

待っ:これについて何

+0

なぜもう一つはコンパイルされませんか?エラーメッセージとは何ですか? 'Select'の後ろに' ToList() 'を追加するとコンパイルされますか?それは 'IEnumerable >'を返すので、 –

+1

です。 – GameScripting

答えて

23

。完了した順番に気をつけなければ理想的です。

EDIT2: でもより良い方法:

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

'Select'ではなく、' WhenAll'の戻り値を使うことができます。これは、各タスクのすべての結果の 'string []'になります。 – Servy

+0

これによれば:http://msdn.microsoft.com/en-us/library/hh194874.aspxそれはあなたが配列を与える場合にのみそれを行います。 –

+3

'ToArray()'、 'Task.WhenAll()'は 'IEnumerable >'でも動作する必要はありません。 – svick

関連する問題