Этот шаблон — удобный способ убедиться, что CancellationTokenRegistration.Unregister()
вызывается автоматически. Его часто использует Стивен Тауб в своих сообщениях в блоге Параллельное программирование с .NET, например. здесь.
Я понимаю, что вы должны убедиться, что вы используете Dispose IDisposable, но почему он вообще реализует IDisposable? какие ресурсы он должен освободить? Единственные методы, которые у него есть, касаются равенства.
ИМО, лучший ответ на этот вопрос можно найти в . NET 4 Cancellation Framework сообщение Майка Лидделла из Microsoft:
Когда обратный вызов регистрируется для CancellationToken
, текущий поток ExecutionContext
захватывается, так что обратный вызов будет выполняться с точно таким же контекстом безопасности. Захват контекста синхронизации текущего потока является необязательным. При необходимости его можно запросить с помощью перегрузки ct.Register()
. Обратные вызовы обычно сохраняются и затем запускаются при запросе отмены, но если обратный вызов регистрируется после запроса отмены, обратный вызов будет выполняться немедленно в текущем потоке или через Send()
в текущем SynchronizationContext
, если применимо.
Когда обратный вызов зарегистрирован для CancellationToken
, возвращаемый объект является CancellationTokenRegistration
. Это легкий тип структуры IDiposable
, и удаление этого объекта регистрации приводит к отмене регистрации обратного вызова. Гарантируется, что после возврата метода Dispose()
зарегистрированный обратный вызов не будет запущен и впоследствии не запустится. Следствием этого является то, что CancellationTokenRegistration.Dispose()
должен блокироваться, если обратный вызов выполняется в данный момент. Следовательно, все зарегистрированные обратные вызовы должны быть быстрыми и не блокироваться на какое-либо значительное время.
Другой соответствующий документ Майка Лидделла: «Использование поддержки отмены в .NET Framework 4» (UsingCancellationinNET4.pdf).
Обновлено, это можно проверить здесь, в справочнике Источник.
Также важно отметить, что обратный вызов отмены регистрируется с помощью CancellationTokenSource
, а не CancellationToken
. Таким образом, если область действия CancellationTokenRegistration.Dispose()
определена неправильно, регистрация останется активной в течение всего времени существования родительского объекта CancellationTokenSource
. Это может привести к неожиданному обратному вызову, когда область действия асинхронной операции исчерпана, например:
async Task TestAsync(WebClient wc, CancellationToken token)
{
token.Register(() => wc.CancelAsync());
await wc.DownloadStringAsync(new Uri("http://www.hamster.com"));
}
// CancellationTokenSource.Cancel() may still get called later,
// in which case wc.CancelAsync() will be invoked too
Таким образом, важно ограничить одноразовый CancellationTokenRegistration
с помощью using
(или явно вызвать CancellationTokenRegistration.Dispose()
с помощью try/finally
).
person
noseratio
schedule
09.02.2014
IDisposable.Dispose
как существующий с целью очистки ресурсов или с целью обеспечения того, чтобы что-то, что необходимо сделать, было выполнено (очистка ресурсов является доминирующим типом необходимых действий). , но не единственный). - person supercat   schedule 09.02.2014