Является ли перехват 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
блок. Но если вы получите токен в качестве параметра, пусть будет выдано исключение.