Является ли код, который удаляет CancellationTokenSource при отмене задач, правильным?

Я вижу этот код передо мной, и я с подозрением

CancellationTokenSource _cts;

public void Dispose();
{
    _cts.Cancel();
    _cts.Dispose();
    _task.Wait(); //wait for the task to be canceled!?
}

Безопасно ли вызывать _cts.Dispose() сразу после отмены? Разве это не будет распоряжаться базовыми ресурсами CancellationTokenSource, которые необходимы для успешного отмены задачи, чтобы дождаться CancellationToken, если он этого хочет?

1 ответ

Решение

Безопасно ли вызывать _cts.Dispose() сразу после отмены?

Чтобы узнать это, нам нужно понять, что происходит, когда мы отменяем CancellationTokenSource,

Когда вы отменяете CancellationTokenSource, он продолжает вызывать любые обратные вызовы, зарегистрированные через CancellationToken, который содержит ссылку на свой родительский источник через CancellationToken.Register() метод.

Теперь, когда вы располагаете CTS, любая попытка обратного вызова связывания, которая была зарегистрирована, пытается отменить регистрацию в токене. Если он выполняется в настоящий момент, он будет ждать, пока его делегат не будет завершен.

Это означает, что хотя вы удалили свой CTS, на его объект все еще ссылается токен. Следовательно, он все еще не имеет права на сбор.

Теперь давайте посмотрим на CancellationToken.IsCancellationRequested:

public bool IsCancellationRequested 
{
    get
    {
        return m_source != null && m_source.IsCancellationRequested;
    }
}

Это означает, что при утилизации проверка отмены даст значение true. Это означает, что для вас безопасно дождаться завершения задач после вызова dispose.

В качестве примечания: если вы (по какой-то причине) попытаетесь передать токен через его аннулированный CancellationTokenSource, вы получите ObjectDisposedException,

Редактировать:

Две вещи, которые я хочу добавить. Во-первых, позвольте мне сказать, что я не рекомендую использовать этот подход. Это должно работать для некоторых путей выполнения кода, но не для всех. CancellationTokenSource должен быть утилизирован, только если вы используете его WaitHandle имущество. В противном случае, можно оставить дело ГХ для очистки. Но, поскольку это вопрос вкуса, вы можете выбрать то, что вам нравится. Я бы определенно посоветовал утилизировать только после того, как вы убедитесь, что задание выполнило запрос на отмену

Согласно использованию WaitHandle, он будет утилизирован и аннулирован, как только вы утилизируете, поэтому он не будет доступен.

Другие вопросы по тегам