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

foreach (var guid in guids)
{
    var task = new Task( ...);
    tasks.Add(task);
}

foreach (var task in tasks)
{
    task.Start();
    Task.WaitAll(task);
}

これはUIスレッドの実行です。タスク変数内のすべてのタスクを次々に実行する必要があります。問題は、Task.WaitAll(task)を呼び出すと、UIがフリーズすることです。UIをフリーズせずに次のロジックを実行するにはどうすればよいですか?

4

3 に答える 3

32

これはタスクチェーンではありません。

を使用してタスクチェーンを実行する必要がありますContinueWith。最後のタスクでは、UIを更新する必要があります。

Task.Factory.StartNew( () => DoThis())
   .ContinueWith((t1) => DoThat())
   .ContinueWith((t2) => UpdateUi(), 
       TaskScheduler.FromCurrentSynchronizationContext());

最後の行にはTaskScheduler.FromCurrentSynchronizationContext()、タスクが同期コンテキスト(UIスレッド)で実行されることが保証されることに注意してください。

于 2012-07-25T12:26:54.507 に答える
16

最善の方法は、タスク並列ライブラリ(TPL)継続を使用することです。継続により、タスクのフローを作成できるだけでなく、例外を処理することもできます。これはTPLの優れた入門書です。しかし、あなたにいくつかのアイデアを与えるために...

を使用してTPLタスクを開始できます

Task task = Task.Factory.StartNew(() => 
{
    // Do some work here...
});

ここで、先行タスクが(エラーまたは正常に)終了したときに2番目のタスクを開始するには、このContinueWithメソッドを使用できます。

Task task1 = Task.Factory.StartNew(() => Console.WriteLine("Antecedant Task"));
Task task2 = task1.ContinueWith(antTask => Console.WriteLine("Continuation..."));

したがって、task1完了するか、失敗するか、キャンセルされるとすぐにtask2「起動」して実行を開始します。task1コードの2行目に到達する前に完了した場合は、task2すぐに実行するようにスケジュールされることに注意してください。2番目のantTaskラムダに渡される引数は、先行タスクへの参照です。より詳細な例については、このリンクを参照してください...

先行タスクからの継続結果を渡すこともできます

Task.Factory.StartNew<int>(() => 1)
    .ContinueWith(antTask => antTask.Result * 4)
    .ContinueWith(antTask => antTask.Result * 4)
    .ContinueWith(antTask =>Console.WriteLine(antTask.Result * 4)); // Prints 64.

ノート。提供されている最初のリンクで例外処理を必ず読んでください。これにより、新規参入者がTPLを誤ってしまう可能性があります。

特に必要なものについて最後に確認する必要があるのは、子タスクです。子タスクは、として作成されるタスクですAttachedToParent。この場合、すべての子タスクが完了するまで継続は実行されません

TaskCreationOptions atp = TaskCreationOptions.AttachedToParent;
Task.Factory.StartNew(() =>
{
    Task.Factory.StartNew(() => { SomeMethod() }, atp);
    Task.Factory.StartNew(() => { SomeOtherMethod() }, atp); 
}).ContinueWith( cont => { Console.WriteLine("Finished!") });

これがお役に立てば幸いです。

于 2012-07-25T12:29:33.307 に答える
5

継続を使用する必要があります:

lastTask.ContinueWith(() => newTask.Start());
于 2012-07-25T12:26:13.583 に答える