Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

C#辞典

  1. トップページ
  2. C#辞典
  3. Task.Run() / Task.Delay()

Task.Run() / Task.Delay()

バックグラウンドでタスクを実行したり、指定時間だけ待機したりする静的メソッドです。複数タスクを並列実行する『WhenAll()』『WhenAny()』も合わせて解説します。

構文
using System.Threading.Tasks;

// バックグラウンドスレッドで処理を実行します。
Task task = Task.Run(() => 処理);
Task<T> task = Task.Run(() => 戻り値のある処理);

// 指定ミリ秒だけ非同期で待機します。
await Task.Delay(ミリ秒);

// すべてのタスクが完了するまで待機します。
await Task.WhenAll(task1, task2, task3);

// 最初に完了したタスクだけを待機します。
Task first = await Task.WhenAny(task1, task2, task3);
メソッド一覧
メソッド概要
Task.Run(action)スレッドプールでデリゲートを実行し、その完了を表す『Task』を返します。
Task.Delay(ms)指定ミリ秒後に完了する『Task』を返します。スレッドをブロックしません。
Task.WhenAll(tasks)すべてのタスクが完了するまで非同期で待機します。
Task.WhenAny(tasks)最初に完了したタスクを返します(タイムアウト実装に便利)。
Task.CompletedTask即完了済みの『Task』を返します(同期的に完了する場合の戻り値に使います)。
task.Wait()タスクが完了するまで現在のスレッドをブロックします。
task.Resultタスクの結果を同期的に取得します(完了まで待機)。
サンプルコード
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

// Task.Run でバックグラウンド処理を実行します。
Task<int> bgTask = Task.Run(() =>
{
    int sum = 0;
    for (int i = 1; i <= 100; i++) sum += i;
    return sum;
});
Console.WriteLine(await bgTask); // 5050

// Task.Delay で非同期にスリープします(Thread.Sleep の代替)。
Console.WriteLine("処理開始");
await Task.Delay(1000); // 1 秒待機
Console.WriteLine("1 秒後");

// WhenAll: 複数のタスクを並列実行してすべての完了を待ちます。
Task<string> t1 = Task.Run(async () => { await Task.Delay(100); return "タスク1"; });
Task<string> t2 = Task.Run(async () => { await Task.Delay(200); return "タスク2"; });
Task<string> t3 = Task.Run(async () => { await Task.Delay(50);  return "タスク3"; });

string[] results = await Task.WhenAll(t1, t2, t3);
Console.WriteLine(string.Join(", ", results)); // タスク1, タスク2, タスク3

// WhenAny: 最初に完了したタスクを取得します(タイムアウト実装例)。
Task<int> longTask = Task.Run(async () => { await Task.Delay(5000); return 42; });
Task timeoutTask = Task.Delay(1000);

Task finished = await Task.WhenAny(longTask, timeoutTask);
if (finished == timeoutTask)
    Console.WriteLine("タイムアウト");
else
    Console.WriteLine($"完了: {longTask.Result}");
概要

『Task.WhenAll()』は複数の非同期処理を並列で走らせ、すべての完了を待ちます。逐次的に『await』を重ねるより合計待機時間を短縮できます。

『task.Result』や『task.Wait()』を非同期メソッド内で使うとデッドロックが発生することがあります。非同期コードの中では必ず『await』を使ってください。同期的に結果を取得する必要がある場合は『Task.FromResult()』の利用も検討してください。

非同期の基本構文は『async / await』を、非同期処理でのキャンセルは『CancellationToken』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。