3

私はこのコードを実行します:

var cancellation = new CancellationTokenSource();
var cancelledTask1 = .....;//starting new long-running task that accepts cancellation.Token
var cancelledTask2 = .....;//starting new long-running task that accepts cancellation.Token

//then I request cancellation
cancellation.Cancel();
//some task gets cancelled before code below executes
try
{
    //wait for completion (some task is already in cancelled state)
    await Task.WhenAll(cancelledTask1, cancelledTask2);
}
catch (OperationCanceledException e)
{
    Logger.Debug("await WhenAll", e);
}

そして、私は得る

await WhenAll System.Threading.Tasks.TaskCanceledException: A task was canceled.

一部のタスクがすでにキャンセル状態になっているため、スローされると思います。Task.WhenAll子タスクがキャンセルされた場合、メソッドが通常のフローを中断して例外をスローするのはなぜですか? この動作の利点は何ですか?

次に、次の方法を試しますTask.WhenAny

var cancellation = new CancellationTokenSource();
var cancelledTask3 = .....;//starting new long-running task that accepts cancellation.Token

//then I request cancellation
cancellation.Cancel();
//the task gets cancelled before code below executes
try
{
    //wait for completion (the task is already in cancelled state)
    await Task.WhenAny(cancelledTask3);
}
catch (OperationCanceledException e)
{
    Logger.Debug("await WhenAny", e);
}

例外をスローしません。

2 番目の質問はTask.WhenAny、同じケースで例外をスローしないのはなぜですか? どちらのメソッドも、キャンセルされたタスクを同じ方法で処理する必要があると思います。つまり、例外をスローするかどうかのいずれかです。

4

2 に答える 2

3

Task.WhenAnyは a を返しますが、 は a をTask<Task>返しTask.WhenAllますTask。最初の完了/キャンセル/失敗したタスクの状態に関係なく、外側のタスクは正常に完了します。内部タスクは、最初にキャンセルされたタスクです。OperationCanceledExceptionしたがって、がスローされるためには、内部タスクと外部タスクの両方を待機する必要があります。

例えば:

await await Task.WhenAny(cancelledTask3);
于 2017-07-21T23:22:56.223 に答える