5

わかりました。を使用してタスクをキャンセルする方法を理解しましCancellationTokenSourceた。Taskタイプ「種類」がこの例外を自動的に処理するように見えます-それはTask'sStatusを Cancelled に設定します。

これで、まだ実際に を処理する必要がありOperationCancelledExceptionます。それ以外の場合、例外は までバブルしApplication.UnhandledExceptionます。タスク自体はそれを認識し、内部で何らかの処理を行いますが、未処理の例外を回避するために呼び出しコードを try ブロックでラップする必要があります。時々、これは不要なコードのように思えます。ユーザーがキャンセルを押した場合は、キャンセルしますTask(明らかに、タスク自体もそれを処理する必要があります)。他のコード要件が必要だとは思いません。Statusプロパティでタスクの完了ステータスを確認するだけです。

言語設計の観点から、これには特定の理由がありますか? Statusプロパティをキャンセルに設定する他の方法はありますか?

4

2 に答える 2

4

結果を要求している、またはタスクが完了するのを待っている try/catch ブロックで呼び出しコードをラップするだけで済みます。これらは、例外がスローされる状況です。たとえば、タスクを作成するコードはその例外をスローしません。

代替手段が何であるかは明確ではありません-たとえば:

string x = await GetTaskReturningString();

ここでは、タスクを参照する変数がないため、ステータスを明示的に確認することはできません。以下を使用する必要があります。

var task = GetTaskReturningString();
string x = await task;
if (task.Status == TaskStatus.Canceled)
{
    ...
}

...これは利便性が低いだけでなく「何かが起こった」コードの処理を通常の成功パスの途中に移動させます。

さらに、例外でキャンセルを処理することにより、複数の操作がある場合、各タスクを個別にチェックする代わりに、すべての処理を 1 つの catch ブロックに入れることができます。

try
{
    var x = await GetFirstTask();
    var y = await GetSecondTask(x);
}
catch (OperationCanceledException e)
{
    // We don't care which was canceled
}

同じ引数が、スタック内で最初のキャンセルが発生した場所でキャンセルを処理する場合にも適用されます。非同期メソッドの深いスタックがある場合、最も深いメソッドでキャンセルすると、通常の例外伝播と同様に、最上位のタスクがキャンセルされます。 .

于 2014-12-17T13:23:28.633 に答える