CancellationTokenSource is hard to use correctly, especially in concurrent scenarios.
Most CancellationTokenSource methods are booby-trapped with ThrowIfDisposed, especially tricky with .Token and .Cancel(). As for both cases there's something to say for silently returning a None token or not Cancelling, but also something to say for being explicit about it and throwing if it happens.
The problem with that last option though is that there's no way to actually check if the CancellationTokenSource is already disposed, now checking could obviously race but there are no Try## variants of these methods either. This leads to over cautious behavior, wrapping each call in a try block.
Concurrent success and cancellation/failure cases are also fun as Cancel throws if the CTS was already disposed. But for timer based CTS's you really do want to Dispose once some piece of code sucessfully completed. This is prone to races between timeouts that try to cancel and success that tries to dispose. This is 'fixable' by locking on the CTS but it all feels brittle.
The current Cancel api is in my opinion the most egrigious, TryCancel would be a valuable api to add.
Lastly there's the matter of having to Dispose a CTS — but really only in some cases. When the CTS is timer based, to keep the timer queue clean. Failing to do so isn't easy to diagnose and I believe it's a pervasive problem in any corporate codebase not familiar with all the details. Having some diagnostic help like UnobservedTaskException but for unobserved timer based CTS's would be amazing.
Right now CancellationTokenSource feels far from the pit of success while it really doesn't have to.
CancellationTokenSourceis hard to use correctly, especially in concurrent scenarios.Most CancellationTokenSource methods are booby-trapped with
ThrowIfDisposed, especially tricky with.Tokenand.Cancel(). As for both cases there's something to say for silently returning a None token or not Cancelling, but also something to say for being explicit about it and throwing if it happens.The problem with that last option though is that there's no way to actually check if the CancellationTokenSource is already disposed, now checking could obviously race but there are no
Try##variants of these methods either. This leads to over cautious behavior, wrapping each call in a try block.Concurrent success and cancellation/failure cases are also fun as
Cancelthrows if the CTS was already disposed. But for timer based CTS's you really do want toDisposeonce some piece of code sucessfully completed. This is prone to races between timeouts that try to cancel and success that tries to dispose. This is 'fixable' by locking on the CTS but it all feels brittle.The current
Cancelapi is in my opinion the most egrigious,TryCancelwould be a valuable api to add.Lastly there's the matter of having to Dispose a CTS — but really only in some cases. When the CTS is timer based, to keep the timer queue clean. Failing to do so isn't easy to diagnose and I believe it's a pervasive problem in any corporate codebase not familiar with all the details. Having some diagnostic help like
UnobservedTaskExceptionbut for unobserved timer based CTS's would be amazing.Right now
CancellationTokenSourcefeels far from the pit of success while it really doesn't have to.