This seems more a question about the Dispose pattern, then about CancellationToken or anything else. And I am uncertain if you implemented said pattern properly. Here is the official MS Document on the mater:
https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern
And here my interpretation:
There is two levels of Disposing: Dispose and Finalizsation. As the code for both is very similar, often they are combiend into one function (in C# usually it is Dispose one). The main difference is if you relay it to contained classes. You always relay a Dispose call(the relay is usually what Dispose is about). You never relay a Finalization call (Finalisation is between that instance and the GC only).
There are also two cases: One in wich you handle Unmanaged resources directly. And one in wich you handle just another Disposeable class.
Unamanged resource directly
In this case the first thing you do is implement a Finalizer, so at least the GC can reliably clean this up. Then you implement IDisposeable as an additional feature so programmers can use stuff like the using pattern to have it cleaned up deterministic at runtime.
Handling something that implements IDisposeable
You have a resource that implements IDisposeable (say like a Filestream Reference). You implement IDisposeable in your class for the sole purpose of relaying the Dispose() call to said FileStream. This is the way more common case. It would guess it makes about 95-99% of all Dispose Implementations.
One thing to keep in mind here is that "Dispose" and "Finalize" often implies lower level cleanup. A SQLConenction you call dispose on will be closed first (if nessesary). A Filehandle you Dispose off will also first be closed. Even if calling cancellationTokenSource.Cancel
was not repeatable, cancellationTokenSource.Dispose
should call Cancel as part of it's operation and should be Repeatable. The class itself does implement IDisposeable. And if any class does, it is usually saver to just call Dispose rather then manually doing the cleanup manually via Cancel: https://learn.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=netframework-4.7.2