Является ли перехват 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;
}

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

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 - это то, о чем они должны беспокоиться, и процессы могут аварийно завершить работу. в результате они не улавливают эти исключения (на переднем плане или в фоновых потоках).

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

1 ответ

Решение

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

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

Другие вопросы по тегам