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をフリーズせずに次のロジックを実行するにはどうすればよいですか?
これはタスクチェーンではありません。
ContinueWith
を使用してタスクチェーンを実行する必要があります。最後のタスクでは、UIを更新する必要があります。
_Task.Factory.StartNew( () => DoThis())
.ContinueWith((t1) => DoThat())
.ContinueWith((t2) => UpdateUi(),
TaskScheduler.FromCurrentSynchronizationContext());
_
注最後の行にはTaskScheduler.FromCurrentSynchronizationContext()
があります。これにより、タスクが同期コンテキスト(UIスレッド)で実行されるようになります。
最良の方法は、タスク並列ライブラリ(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
'が起動し、実行を開始します。コードの2行目に到達する前にtask1
が完了した場合、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!") });
これがお役に立てば幸いです。
継続を使用する必要があります:
lastTask.ContinueWith(() => newTask.Start());