Должен ли я всегда добавлять CancellationToken к своим действиям контроллера?
Это хорошая практика, чтобы всегда добавлять CancellationToken в мои действия, независимо от того, длительная операция или нет?
В настоящее время я добавляю его в каждое действие и не знаю, правильно это или нет.
[Route("api/[controller]")]
public class DummiesController : Controller
{
private readonly AppDbContext _dbContext;
public DummyController(AppDbContext dbContext)
{
_dbContext = dbContext;
}
[HttpGet("{id}")]
public async Task<ActionResult<Dummy>> GetAsync(int id, CancellationToken ct) // <<----- should I always do this?
{
var dummy = await _dbContext.Dummies.AsNoTracking().SingleOrDefaultAsync(e=>e.Id == id, ct);
if (dummy == null) return NotFound();
return dummy;
}
}
Также добавляется CancellationToken ct = default(CancellationToken)
необходимо?
5 ответов
Должен ли я всегда добавлять CancellationToken к действиям моего контроллера?
Нет, не всегда.
Использование CancellationTokens в контроллерах MVC ASP.NET Core
https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/
Правильность этого поведения будет зависеть от вашего приложения. Если запрос изменяет состояние, возможно, вы не захотите останавливать выполнение на полпути через метод. С другой стороны, если запрос не имеет побочных эффектов, вы, вероятно, захотите остановить (предположительно дорогостоящее) действие как можно скорее.
Итак, если у вас есть метод / действие, как показано ниже (упрощено);
await ProcessOrder();
await UpdateInventory();
Вы не хотите отменять заказ, пока он обрабатывается, в этом случае заказ может быть выполнен, но вы не обновите инвентарь, если пользователь проходит через туннель и теряет подключение к Интернету.
Это особенно важно, когда операции не могут быть включены в шаблон, подобный единице работы (например, распределенная система), и нужно попытаться минимизировать отмены.
Стоит добавить, если у вас есть зависимость от внешнего ресурса.
Допустим, ваша база данных занята, или у вас есть временные политики обработки ошибок / повторных попыток для вашего подключения к базе данных. Если конечный пользователь нажимает "Стоп" в своем браузере, токен отмены поможет корректно отменить все операции ожидания (в вашем коде).
Меньше думайте о долгосрочной природе в нормальных условиях, но о долгосрочной природе не в идеальных условиях, например, если в Azure и в вашей базе данных SQL выполняется плановое обслуживание, а структура сущностей настроена на повторную попытку (предполагается, что платформа Entity реагирует на отмену). жетоны разумно).
В качестве примечания: инфраструктура устойчивости Polly имеет отличную поддержку внешних токенов отмены, чтобы координировать отмены повторов из внешнего отмены. Их вики стоит прочитать, так как это отличная возможность для координации отмены: https://github.com/App-vNext/Polly/wiki
относительно CancellationToken ct = default(CancellationToken)
это, вероятно, более полезно для библиотечного кода, чем для действия контроллера. Но удобно, если вы тестируете свой контроллер напрямую, но не хотите передавать токен отмены. Сказав, что тестовую рамку WebHostBuilder ядра.net легче тестировать, чем тестировать действия контроллера непосредственно в эти дни.
Я думаю, что токен отмены следует использовать в основном для операций типа запроса. В качестве примера возьмем операцию CRUD (создание, чтение, обновление, удаление), разбив ее на CQRS (разделение ответственности за запросы команд).
- Команда: Создать, Обновить, Удалить
- Запрос: Читать
Как видите, операцию запроса не составит труда отменить в любой момент. Но для Command вы, скорее всего, не захотите отменять какие-либо операции. Например, Create, представьте, что вы создаете данные для двух отдельных баз данных, а затем были отменены на полпути, это приведет к несинхронизации данных.
Я думаю, что вопрос больше в принципе, а не в зависимости от действия. Когда я запускаю новое приложение, в основном REST API, я всегда задаюсь вопросом: «Должен ли я включить CancellationToken во все мои асинхронные ActionResult в качестве стандарта». Если я этого не сделаю, пожалею ли я об этом? Хорошо, что представляет собой длительную задачу? Что, если задача, которая должна была быть недолгой, под капотом стала долгой. И, как в прошлом @Konrad, я не знаю ответа.
Другой подход заключается в отмене любых операций, а не только операций запроса.
Когда вы копируете файл в Windows и нажимаете кнопку «Отмена», операция немедленно останавливается. То же самое и для веб-приложений. Если пользователь нажмет кнопку сохранения, а затем закроет браузер, не дожидаясь завершения операции, операция сохранения может быть немедленно остановлена.
Для длительной операции пользовательский интерфейс может отображать диалоговое окно с текстом «Подождите» и кнопкой отмены. Это сделало бы поведение более удобным для пользователя.