Подтвердить что ты не робот

Захватывает 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;
}

Это, очевидно, означает, что вызывающему абоненту, вероятно, необходимо проверить сам маркер отмены, чтобы определить, продолжать ли обработку, и им, возможно, придется обрабатывать null retVals:

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

Однако, если мы примем второй стиль кода (B), который полагается на TaskCanceledException:

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

Код реализации определенно проще - и у вызывающего есть возможность обработать исключение или нет, если это необходимо... но я не могу не беспокоиться о том, что вызывающие могут забыть, что TaskCanceledException - это то, о чем им нужно беспокоиться, и процессы могут вылетать из-за того, что они не улавливают эти исключения (на переднем или заднем потоках).

Итак, мой чрезмерно оптимистично сформулированный вопрос: каким, по вашему мнению, является лучший стиль, который каждый должен всегда использовать, и почему?:)

4b9b3361

Ответ 1

В самой инфраструктуре .Net, когда вы передаете CancellationToken в качестве параметра, вы вернетесь к TaskCanceledException. Я бы не пошел против этого и создал свой собственный шаблон дизайна, потому что люди, знакомые с .Net, будут знакомы с вашим кодом.

Мое правило таково: тот, который отменяет токен, тот, который должен обрабатывать TaskCanceledException, поэтому, если вы используете CancellationToken внутри своего метода по вашим собственным причинам, продолжайте использовать try-catch блок. Но если вы получите токен в качестве параметра, пусть исключение будет выбрано.