web-dev-qa-db-ja.com

TaskCanceledExceptionをキャッチしてTask.Canceledをチェックするのは良い考えですか?

私のチームには、async Taskを使用したコーディングが大好きな人がいます。また、CancellationTokenパラメータを使用したい場合もあります。

私が確信していないのは、チームとしてこのスタイルのコードを使用する必要があるかどうかです(A):

async Task<someObject> DoStuff(CancellationToken t)
{
    while (!t.IsCanceled)
    {
        try {
            Task.Delay(5000, t);
        }
        catch (AggregateException e) // or is it TaskCanceledException or OperationCanceledException? I don't know? :)
        {
        }
        // poll something, return someObject, or null
    }
    return null;
}

これは明らかに、呼び出し元が処理を続行するかどうかを決定するためにキャンセルトークン自体をチェックする必要があり、nullretValsを処理する必要がある可能性があることを意味します。

var retVal = await DoStuff(token);
if (token.IsCanceled) { ... }

ただし、TaskCanceledExceptionに依存する2番目のスタイルのコード(B)を採用する場合:

async Task<someObject> DoStuff(CancellationToken t)
{
    while(true)
    {
        Task.Delay(5000, t);
        // poll something, return someObject, or null
    }
}

実装コードは間違いなく単純です-そして、呼び出し元は必要に応じて例外を処理するかどうかのオプションがあります...しかし、呼び出し元がそうするかもしれないことを心配せずにはいられません忘れる TaskCanceledExceptionは彼らがしなければならないものです心配してください。プロセスがこれらの例外をキャッチしない結果としてクラッシュする可能性があります(フォアグラウンドまたはバックグラウンドスレッドで)。

だから、私の過度に楽観的に表現された質問は次のとおりです:最高スタイルはみんなすべき常に、そしてなぜですか? :)

21

.Net Framework自体で、 CancellationToken をパラメーターとして渡すと、 TaskCanceledException が返されます。 .Netに精通している人はあなたのコードに精通しているので、私はそれに反対せず、独自のデザインパターンを作成します。

私のガイドラインは次のとおりです。トークンをキャンセルするのはTaskCanceledExceptionを処理する必要があるため、独自の理由でメソッド内でCancellationTokenを使用している場合は、先に進んで使用してください。 try-catchブロック。 ただし、トークンをパラメーターとして取得する場合は、例外をスローします

31
i3arnon