Захватывает 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 - это то, о чем им нужно беспокоиться, и процессы могут вылетать из-за того, что они не улавливают эти исключения (на переднем или заднем потоках).
Итак, мой чрезмерно оптимистично сформулированный вопрос: каким, по вашему мнению, является лучший стиль, который каждый должен всегда использовать, и почему?:)
Ответы
Ответ 1
В самой инфраструктуре .Net, когда вы передаете CancellationToken
в качестве параметра, вы вернетесь к TaskCanceledException
. Я бы не пошел против этого и создал свой собственный шаблон дизайна, потому что люди, знакомые с .Net, будут знакомы с вашим кодом.
Мое правило таково: тот, который отменяет токен, тот, который должен обрабатывать TaskCanceledException
, поэтому, если вы используете CancellationToken
внутри своего метода по вашим собственным причинам, продолжайте использовать try-catch
блок. Но если вы получите токен в качестве параметра, пусть исключение будет выбрано.