Должен ли я предпочесть бросок или возврат при отмене? - PullRequest
0 голосов
/ 24 октября 2018

Рассмотрим два следующих подхода к обработке отмены через CancellationToken:

public async Task DoAllAvailableWork(CancellationToken cancelToken)
{
    foreach (var job in GetAllAvailableWork())
    {
        await job.Process();

        if (cancelToken.IsCancellationRequested())
            return;
    }
}

public async Task DoAllAvailableWork(CancellationToken cancelToken)
{
    foreach (var job in GetAllAvailableWork())
    {
        await job.Process();

        cancelToken.ThrowIfCancellationRequested();
    }
}

В этом случае job.Process() выполняет некоторую атомарную работу, которая не должна или не может быть остановлена ​​после ее начала, поэтому она делаетне принять CancellationToken.

Есть ли основания предпочитать один из этих подходов другому?Если да, какой подход следует предпочесть?

Проверка IsCancellationRequested() и возвращение мне кажутся чище, в том смысле, что бросание подразумевает, что что-то пошло не так, и отмена - это случай, который мы явно планировали обработать (этопочему мы принимаем CancellationToken).С другой стороны, вызывающий абонент не обязательно может знать, какой подход мы выберем, поэтому он должен настроить try / catch для OperationCancelledException независимо от того, какой вариант мы выберем.

1 Ответ

0 голосов
/ 24 октября 2018

ThrowIfCancellationRequested предназначен для продолжения задач.Бросок останавливает всю цепочку продолжения (за исключением продолжений обработки отмены).Необработанное OperationCancelledException в задании также отменит токен отмены Task (если есть).

В вашем случае Task нет.Вы можете определить свой собственный интерфейс.Но имейте в виду, что тот, кто вызывает ваш метод, должен также иметь возможность увидеть, была ли ваша операция отменена или нет - в конце концов, что-то еще должно было вызвать отмену, если все, что у вас есть, - синхронные методы.В зависимости от того, что означает отмена, каждый из них может иметь смысл: возвращать ошибку, пустой результат, false или генерировать исключение (но, возможно, не OperationCancelledException!) - вам нужно адаптировать его к тому типу интерфейса, который вы делаете.

...