The second doesn't properly synchronize access to the memory that you're sharing between multiple threads, and as a result, it won't necessarily function the way that you want it to. For example, the thread pool thread doing the work is allowed to see that it isn't writing to that variable (another thread may be, but it doesn't need to know or care about what other threads are doing when there is no explicit synchronization going on) and so it's free to cache that boolean value rather than fetching it from memory each time it needs it, which it's all the more likely to do given how frequently it's reading that value. This will result in it not noticing the change from the other thread, possibly for quite some time. And of course the fact that this problem won't happen every time will make diagnosing it when it does happen all the more difficult.
CancellationToken
takes care of all of the necessary synchronization so that you don't have to, and it'll do it as efficiently as possible to boot.
It's also often beneficial from a design standpoint. You can separate who is responsible for canceling the operation from who is responsible for acting on that cancellation. There is much looser coupling between your worker and it's caller/consumer as a result. That worker could do work for anyone that wants it to do work; it's not tying the cancellation to a particular variable in a particular location. This is all the more relevant when the entity responsible for canceling the operation is several layers removed from the entity responsible for doing the work. It's a lot easier to pass a cancellationtoken to something that passes it to something that checks it to see when cancellation happens than to try to manage that with just a boolean; it either means one of those entities needs to know explicitly about the other, despite all of the layers of abstraction between them, or it would require encapsulating that boolean in some way analogous to what CancellationToken
does.
Additionally, abstracting out the idea of a cancellation token allows you to create higher level operations that act on/with cancellation tokens. It lets you create a cancellation token that will be cancelled after a set period of time, or to create a cancellation token that is only cancelled when all of a set of tokens are cancelled, or when any of a set of tokens are canceled, etc.