LoginSignup
3
2

More than 5 years have passed since last update.

Task.WhenAllが返すTaskオブジェクトのIsCanceled,IsFaultedの値

Last updated at Posted at 2019-04-18

問題

Task.WhenAllメソッドが返すTaskオブジェクトは、引数であたえられたコレクション内のTaskオブジェクトすべてが完了(あるいは例外、中断)すると、IsCompletedがtrueになる。
では、IsCanceled, IsFaultedプロパティはどうなるか。
複数あるタスクのうち、ひとつだけがキャンセルされたときはどうなるか。
このとき、例外をスローしたタスクが混ざっていた場合はどうか。

検証方法

以下のコードで調査をおこなった。

static void Main(string[] args)
{
    Console.WriteLine("Empty");
    Action(new Task[0]);
    Console.WriteLine("");

    Console.WriteLine("Completed task");
    Action(new[] { CreateNormalTask() });
    Console.WriteLine("");

    Console.WriteLine("Canceled task");
    Action(new[] { CreateCanceledTask() });
    Console.WriteLine("");

    Console.WriteLine("Faulted task");
    Action(new[] { CreateFaultedTask() });
    Console.WriteLine("");

    Console.WriteLine("Completed task & Canceled task");
    Action(new[] { CreateNormalTask(), CreateCanceledTask() });
    Console.WriteLine("");

    Console.WriteLine("Complated task & Fauleted task");
    Action(new[] { CreateNormalTask(), CreateFaultedTask() });
    Console.WriteLine("");

    Console.WriteLine("Canceled task & Fauleted task");
    Action(new[] { CreateCanceledTask(), CreateFaultedTask() });
    Console.WriteLine("");

    Console.WriteLine("Completed task & Canceled task & Fauleted task");
    Action(new[] { CreateNormalTask(), CreateCanceledTask(), CreateFaultedTask() });
    Console.WriteLine("");

    Console.ReadKey();
}

static void Action(Task[] tasks)
{
    var whenAllTask = Task.WhenAll(tasks);
    Console.WriteLine($"WhenAllTask: IsCompleted = {whenAllTask.IsCompleted}, IsCanceled = {whenAllTask.IsCanceled}, IsFaulted = {whenAllTask.IsFaulted}");

    foreach (var pair in tasks.Select((task, index) => new {task, index}))
        Console.WriteLine($"  {pair.index}: IsCompleted = {pair.task.IsCompleted}, IsCanceled = {pair.task.IsCanceled}, IsFaulted = {pair.task.IsFaulted}");
}

static Task CreateNormalTask() => Task.CompletedTask;
static Task CreateCanceledTask()
{
    var source = new TaskCompletionSource<int>();
    source.TrySetCanceled();
    return source.Task;
}
static Task CreateFaultedTask()
{
    var source = new TaskCompletionSource<int>();
    source.TrySetException(new Exception());
    return source.Task;
}

実行結果一覧

正常終了したタスク キャンセルされたタスク 例外をスローしたタスク IsCompleted IsCanceled IsFaulted
あってもなくても なし なし true false false
あってもなくても あり なし true true false
あってもなくても あってもなくても あり true false true

詳細は以下のとおり。

Empty
WhenAllTask: IsCompleted = True, IsCanceled = False, IsFaulted = False

Completed task
WhenAllTask: IsCompleted = True, IsCanceled = False, IsFaulted = False
  0: IsCompleted = True, IsCanceled = False, IsFaulted = False

Canceled task
WhenAllTask: IsCompleted = True, IsCanceled = True, IsFaulted = False
  0: IsCompleted = True, IsCanceled = True, IsFaulted = False

Faulted task
WhenAllTask: IsCompleted = True, IsCanceled = False, IsFaulted = True
  0: IsCompleted = True, IsCanceled = False, IsFaulted = True

Completed task & Canceled task
WhenAllTask: IsCompleted = True, IsCanceled = True, IsFaulted = False
  0: IsCompleted = True, IsCanceled = False, IsFaulted = False
  1: IsCompleted = True, IsCanceled = True, IsFaulted = False

Complated task & Fauleted task
WhenAllTask: IsCompleted = True, IsCanceled = False, IsFaulted = True
  0: IsCompleted = True, IsCanceled = False, IsFaulted = False
  1: IsCompleted = True, IsCanceled = False, IsFaulted = True

Canceled task & Fauleted task
WhenAllTask: IsCompleted = True, IsCanceled = False, IsFaulted = True
  0: IsCompleted = True, IsCanceled = True, IsFaulted = False
  1: IsCompleted = True, IsCanceled = False, IsFaulted = True

Completed task & Canceled task & Fauleted task
WhenAllTask: IsCompleted = True, IsCanceled = False, IsFaulted = True
  0: IsCompleted = True, IsCanceled = False, IsFaulted = False
  1: IsCompleted = True, IsCanceled = True, IsFaulted = False
  2: IsCompleted = True, IsCanceled = False, IsFaulted = True

結論

Task.WhenAllが返すタスクについて、IsComplatedがtrueのとき、

  • IsCanceledの値では、キャンセルされたタスクがないことはわからない。例外をスローしたタスクがひとつでもあると、必ずfalseになる。
  • IsFaultedの値によって、例外をスローしたタスクがあるかどうかがわかる
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2