#c# #.net #task-parallel-library #task #cancellation-token
#c# #.net #task-parallel-library #задача #отмена-токен
Вопрос:
В моей команде есть люди, которым действительно нравится кодирование с использованием 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:
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. Меня интересует ответ (ы) на этот вопрос, и у меня тоже есть свой собственный, но я подозреваю, что этот вопрос запрашивает мнение, которое не совсем соответствует теме для SO. Рассматривали ли вы возможность запросить помощь модератора в переносе этого в codereview вместо этого?
2. Я думаю, что мнение полностью соответствует теме для SO в случае «что, по вашему мнению, является хорошей практикой программирования».
3. Я также не считаю это вопросом проверки кода, поскольку он нацелен на конкретную тему, это не «скажите мне, как лучше это закодировать».
4. Я не испытывал по этому поводу особых чувств; это просто выглядело похоже на субъективный вопрос (ы), которые были отмечены в прошлом. Я рад, что это получает хорошее обсуждение 🙂
5. @TimLovell-Smith, вы никогда не должны проглатывать
AggregateException
, как в вашем коде, без проверки внутренних исключений. Кроме того, это может быть либоOperationCanceledException
, либоTaskCanceledException
. Проверьте этот документ: Использование поддержки отмены в .NET 4.0 .
Ответ №1:
В .Сама Net framework, когда вы передаете a CancellationToken
в качестве параметра, вы получите обратно a TaskCanceledException
. Я бы не пошел против этого и не создал свой собственный шаблон проектирования, потому что люди, которые знакомы с .Net будет знаком с вашим кодом.
Мое руководство таково: тот, который отменяет токен, должен обрабатывать TaskCanceledException
, поэтому, если вы используете CancellationToken
внутри своего метода по своим собственным причинам, продолжайте и используйте try-catch
блок. Но если вы получаете токен в качестве параметра, пусть генерируется исключение.
Комментарии:
1. Отличный ответ за включение руководства по кодированию для обеспечения обработки исключений!
2. Хороший ответ — но было бы неплохо увидеть несколько примеров кода в том же духе, что и вопрос организации.
3. Кроме того, обычно рекомендуется перехватывать,
OperationCanceledException
как указано в статье «Рекомендуемые шаблоны для CancellationToken» (раздел «Обработка исключений отмены»).