Во-первых, когда вы вызываете CancellationToken.Register
, все, что он обычно делает, это сохраняет делегат для вызова позже.
Поток / логический поток, вызывающий CancellationTokenSource.Cancel
, запускает все ранее зарегистрированные делегаты, независимо ототкуда те были зарегистрированы.Это означает, что любое исключение, выдаваемое в тех, которые обычно не связаны, никак не связано с методами, которые вызывали Регистр .
Примечание 1: Я сказал обычно выше, потому что есть случай, когда вызов Register
сразу же запустит делегата.Я думаю, именно поэтому документация msdn очень запутана.В частности: если токен уже был отменен, Register
сразу же запустит делегат, а не сохранит его для запуска позже.Внизу, что происходит в CancellationTokenSource.InternalRegister
.
Второе, что завершает картину, это то, что все, что CancellationToken.ThrowIfCancellationRequested
делает, - это генерирует исключение, откуда бы оно ни запускалось.Обычно это было бы там, откуда CancellationTokenSource.Cancel
был вызван.Обратите внимание, что обычно все зарегистрированные делегаты запускаются, даже если некоторые из них выдают исключение.
Примечание 2: throwing ThreadAbortException
изменяет предполагаемую логику в методе Cancel
, потому чтоэто особое исключение не может быть поймано.Когда сталкиваешься с этим, отмена прекращает работу дальнейших делегатов.То же самое происходит с вызывающим кодом, даже при перехвате исключений.
Последнее, на что нужно обратить внимание, это то, что наличие CancellationToken не влияет на логический поток методов.Все строки в методе выполняются, если только нет явного выхода из метода, например, с помощью исключения.Это то, что происходит, если вы передаете токен отмены вызовам Task.Delay, и он отменяется откуда-то еще до истечения времени.Это также то, что происходит, если вы должны были вызывать CancellationToken.ThrowIfCancellationRequested
после определенных строк в вашем методе.