Исключение при отмене задачи

Итак, согласно ответу на этот пост :

2) Если тело задачи также отслеживает токен отмены и генерирует исключение OperationCanceledException, содержащее этот токен (что и делает ThrowIfCancellationRequested), то, когда задача видит этот OCE, она проверяет, соответствует ли токен OCE маркеру задачи. Если это так, это исключение рассматривается как подтверждение совместной отмены, и задача переходит в состояние «Отменено» (а не в состояние «Ошибка»).

Из этого я понял, что, передав токен конструктору задачи, а затем вызвав метод ThrowIfCancellationRequested() того же токена, задача на самом деле завершится мирно, без необходимости явного перехвата OperationCanceledException.

Однако, как выясняется, выбрасывается исключение, поэтому я полагаю, что, возможно, неправильно понял механику.

Мой код:

  public void AI()
    {
        IsBusy = true;
        var token = stopGameCancellationTokenSource.Token;
        var workTask = new Task(() => aiWork(token), token);
        workTask.Start();
        workTask.ContinueWith(task => { IsBusy = false; });

    }

    private void aiWork(CancellationToken token)
    {

        while ( true)
        {

             //Some computation being done here

            token.ThrowIfCancellationRequested(); //Exception is thrown here, I thought it wouldn't

            //More computation here, which I don't want to happen if cancellation has benn requested
        }
    }

person Gabriel Asman    schedule 21.04.2015    source источник


Ответы (3)


Эта линия

token.ThrowIfCancellationRequested();

явно выдает исключение. Ссылка говорила вам, что если токен задачи совпадает с токеном в только что выброшенном OperationCanceledException, «задача переходит в состояние «Отменено» (а не в состояние «Ошибка»)».

Итак, суть в том, что если вы не хотите, чтобы при отмене задачи возникало исключение, просто пропустите эту строку!

person Jurgen Camilleri    schedule 21.04.2015

В дополнение к объяснению в ответе @JurgenCamilleri о почему вы получаете сообщение об ошибке, что вы вероятно, намеревался сделать цикл, пока не будет запрошена отмена. Вы можете сделать это, изменив свой код на что-то вроде этого:

private void aiWork(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        //Some computation being done here

        if (token.IsCancellationRequested)
            break; // need to cancel

        //More computation here, which I don't want to happen if cancellation has been requested
    }
}    
person Alex    schedule 21.04.2015

Как следует из названия метода, ThrowIfCancellationRequested вызовет исключение (OperationCanceledException), если была запрошена отмена.

Если вы действительно не хотите, чтобы возникало исключение, вы можете проверить, является ли token.IsCancellationRequested истинным, и в этом случае выйти из вашей функции. Тем не менее, я бы рекомендовал придерживаться token.ThrowIfCancellationRequested(), если у вас нет веских причин не делать этого.

person Tom C.    schedule 21.04.2015