I don't like it - you're forced to pass around this token, constantly manage the lifecycle of cancellation sources - and incredibly bug prone thing in async context, and it quickly gets very confusing when you have multiple tokens/sources.

I understand why they did it - a promise essentially is just some code, and a callback that will be triggered by someone at some point in time - you obviously get no quality of service promises on what happens if you cancel a promise, unless you as a dev take care to offer some.

It's also obvious that some operations are not necessarily designed to be cancellable - imagine a 'delete user' request - you cancelled it, now do you still have a user? Maybe, maybe you have some cruft lying around.

But still, other than the obvious wrong solution - C# had a Thread.Abort() similar to the stop() function that you mentioned, that was basically excommunicated from .NET more then a decade ago, I'm still not happy with the right one.

    > ...constantly manage the lifecycle of cancellation sources
Very rare unless you are spawning your own.

Usually, you are passing through a runtime provided token (e.g. ASP.NET).

Not that rare in my experience, I constantly had to write software like this. Not every day, but it certainly did come up quite often in my code and others'

Oh and oone more thing - the very (developer-managed) complexity makes it that people constantly got it wrong, usually just enough (as often with the case of threading) that it worked fine 90% of the time, and was very hard to make a case to management why we should invest effort into fixing it.

Not rare in the slightest. C# is used in a lot of places that aren't the web and don't have extra frameworks piled on.

If you're writing a bare C# library for desktop deployment, you're managing your own cancellation sources.

Cancelling a token doesn't immediately abort the underlying Task. It is up to the implementation of that task to poll the token and actively decide when to abort.

In your example, you'd design your delete task such that if you want it to be cancelable, it can only be canceled before data is modified. You simply don't abort in the middle of a database transaction.

Moreover, because of the way cancellation tokens work, you can't abort blocking function calls unless you also pass the token along. There just isn't a mechanism that can interrupt a long IO operation or whatever unless you explicitly go to the effort to make that happen.

A cancellation token is more of a "pretty please stop what you're doing when you feel like it" concept than Thread.Abort().