2017-01-16 6 views
2

すでにTask.WhenAllが待機しているタスクをリストに追加することはできませんか?Task.WhenAllが待機しているコレクションにタスクを追加する方法はありますか?

すべてのタスクが完了するのを待っていて、初期化後に新しいタスクを作成する可能性があります。しかし、ここではTask.WhenAllは後でコレクションに追加される新しいタスクを待つことはありません。

List<Task> tasks = new List<Task>(); 

var task1 = Task.Run(async() => 
    { 
     Debug.WriteLine("task #1 started"); 
     await Task.Delay(TimeSpan.FromSeconds(20)); 
     Debug.WriteLine("task #1 finished"); 
    }); 

var task2 = Task.Run(async() => 
{ 
    Debug.WriteLine("task #2 started"); 
    await Task.Delay(TimeSpan.FromSeconds(30)); 
    Debug.WriteLine("task #2 finished"); 
}); 

var task3 = Task.Run(async() => 
{ 
    Debug.WriteLine("task #3 started"); 
    await Task.Delay(TimeSpan.FromSeconds(10)); 
    var inner = Task.Run(async() => 
    { 
     Debug.WriteLine("inner task started"); 
     await Task.Delay(TimeSpan.FromSeconds(40)); 
     Debug.WriteLine("inner task finished"); 
    }); 

    tasks.Add(inner); 

    Debug.WriteLine("task #3 finished"); 
}); 

tasks.Add(task1); 
tasks.Add(task2); 
tasks.Add(task3); 

await Task.WhenAll(tasks); 
Debug.WriteLine("All finished"); 

出力:tasks.Add(inner)await Task.WhenAll(tasks)後に実行されるため

task #2 started 
task #3 started 
task #1 started 
task #3 finished 
inner task started 
task #1 finished 
task #2 finished 
All finished 
inner task finished < didn't wait for this to finish 
+0

[ソース](https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,69351c6da968e5d1)を見ると、コレクション/配列が前にコピーされていることがわかります内部のメカニズムが跳ね上がるので、元のコレクションへの変更は観察されません。 –

+0

私はあなたができることは手作業のループだと思う - while(tasks.Count> 0){Task.WhenAll(tasks);を待つ。タスク=タスク。どこ(t =>!t.IsCompleted); } 'スケッチとして –

+0

@Damien_The_Unbelieverありがとうございます。私はこれが最善の解決策だと思う。あなたは答えとしてそれを書かないでしょうか? – Blendester

答えて

1

Task.WhenAllは常にcopies参照し、それが実際に待って開始する前に。これは、待機中に元のコレクションを更新できることを意味しますが、WhenAllはこれらの変更を完全に無視しています。

代わりに、あなたのWhenAllをループで実行することをお勧めします。線に沿って何か:

while(tasks.Count > 0) { 
    await Task.WhenAll(tasks); 
    tasks = tasks.Where(t => !t.IsCompleted); 
} 

演習は、読者が記入されるよう(あなたがなど、正確な正しいデータ型は、その変数何のためにあるのか、そのままtasks自体を残したいかどうかの正確な詳細で、左)

5

これがあります。あなたの質問に答えるには、まずタスク#3の間の関連性を明確にする必要があります。です。 IMOは内部タスクがタスク#3の一部でなければならない。すなわち、タスク#3は、内部タスクが終了するまで終了することができない。タスクへ

await inner; //instead of tasks.Add(inner); 
+0

ありがとうございます。それはデモンストレーションのためだった。新しいタスクはどこからでも 'tasks'に追加できます。私の問題は、メソッドが終わりに達するとすべてのタスクが完了するようにしたいということです。多分私は間違った質問を解決している – Blendester

関連する問題