CancellationToken
является более вероятным кандидатом для этого, чем IProgress<T>
. С IProgress<T>
у вас часто есть разные T
на разных уровнях (высокоуровневые async
методы объединяют уведомления о прогрессе их низкоуровневых await
вызовов). При CancellationToken
один и тот же токен почти всегда передается методам async
более низкого уровня (при условии, что они поддерживают отмену). CancellationToken
поддерживает некоторые действительно продвинутые комбинаторы, но они почти никогда не используются.
Основным недостатком является то, что вы отходите от асинхронного шаблона на основе задач. Вы должны иметь в виду, что любой код Microsoft или стороннего производителя будет иметь явный CancellationToken
- то есть вам придется явно извлекать его из окружающего контекста в ваших низкоуровневых async
методах. Кроме того, программисты, обслуживающие вашу кодовую базу позже, могут ожидать TAP.
Существует также проблема, когда вы рассматриваете реализацию. Вы бы хотели, чтобы неявный CancellationToken
следовал за вызовами async
методов, даже если они изменяют контексты потока. Я имею в виду, рассмотрим это: метод A
вызывает ConfigureAwait(false)
перед ожиданием результата метода B
. Вы не можете использовать простое локальное статическое свойство потока, потому что вам нужно следовать контексту асинхронного выполнения из одного потока в другой.
Кажется, я вспомнил, как читал о способе сделать это (возможно, с использованием класса CallContext
?), Но как только вы это сделаете, ваши показатели производительности (код миграции контекста исполнения сильно оптимизирован) для сценария по умолчанию).