75

I start a task, that starts other tasks and so forth. Given that tree, if any task fails the result of the whole operation is useless. I'm considering using cancellation tokens. To my surprise, the token does not have a "CancelThisToken()" method...

How can I, in possession of only a CancellationToken, cancel it?

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
Leonardo
  • 9,691
  • 9
  • 56
  • 137
  • 1
    You're looking for CancellationTokenSource https://msdn.microsoft.com/en-us/library/system.threading.cancellationtokensource(v=vs.110).aspx – CoderDennis Jun 16 '15 at 18:26
  • 1
    @CoderDennis I dont see how i can obtain the token source given only the token... – Leonardo Jun 16 '15 at 18:29
  • 2
    If you don't have a `CancellationTokenSource` then you can't cancel it. The token is an object that all the threads share, this object is set by the `CancellationTokenSource.Cancel()` method. Once done so, the `CancellationToken.IsCancellationRequested` would be true. Until then, it will always be false. (It cannot be set directly.) If you don't have a `CancellationTokenSource`, then there is nothing that is capable of throwing the cancellation. You **require** a `CancellationTokenSource` to cancel threads like that. – Der Kommissar Jun 16 '15 at 18:43

4 Answers4

107

As the documentation state, you need to call the cancel method from the source object. Example code is included in the link you provided. Here are the relevant sections:

// Define the cancellation token.
CancellationTokenSource source = new CancellationTokenSource();
previouslyProvidedToken = source.Token;
...
source.Cancel();

CancellationToken Struct

how can I, in possession of only a CancellationToken, cancel it?

Edit: I wrote this years ago and revisiting it I don't know if its actually valid either when written or right now. Leaving it here as-is for posterity.

Without a reference to the source you cannot cancel a token. That doesn't mean that you need the CancellationTokenSource that first spawned the token. When given a CancellationToken, you can create a new instance of the token source, assign it's token to the provided token, and cancel it. All other parties that can read this token will see that it's cancellation has been requested.

RyanS
  • 3,715
  • 3
  • 22
  • 36
  • 1
    @Leonardo, You should first create the tokensource and then request the token from it. Look at the example code in the link I provided – RyanS Jun 16 '15 at 18:32
  • 1
    This is the method I use for our backup utility at work - if any `Task` fails my results are useless as well. (The two databases, one SQL, one AS/400 DB2, are out of sync, and that's unacceptable. So I discard all data if anything fails.) – Der Kommissar Jun 16 '15 at 18:34
  • @Leonardo, If you are still confused after looking at the longer example update your question with your code and I will try to provide more information – RyanS Jun 16 '15 at 18:34
  • 5
    @Leonardo You *can't* get the source when given only the token. it is *by design* that you cannot cancel a token when all you have is that token. It would be a broken system if it could. – Servy Jun 16 '15 at 18:41
  • @RyanS You should probably add something answering the `how can I, in possession of ONLY a CancellationToken, cancel it?` as well. – Der Kommissar Jun 16 '15 at 18:47
  • @EBrown, From my understanding and as Servy commented that is not possible and is not the way to use Cancelation Token – RyanS Jun 16 '15 at 19:24
  • 1
    @RyanS I meant you should add Servy's information (or mine) to the answer. – Der Kommissar Jun 16 '15 at 19:24
  • 2
    Overriding `previouslyProvidedToken` like in the edit is a bad practice... If the source of the provided token is cancelled (on a higher level in the tree), this functionally would not react to that cancel. Passing a CancellationToken would be entirely useless in this case, so Daniel Park's answer offers a better solution. – Sjeijoet Sep 19 '16 at 08:40
  • 1
    @RyanS _"When given a Token, you can create a new instance of token source assign it's token to the provided token and cancel it"_. This is not true, you cannot assign `CancellationTokenSource.Token` property, it is readonly. – JobaDiniz Mar 07 '17 at 19:32
  • @JobaDiniz its been a while since I added this answer but I believe I meant that you could get the token from the tokensource and assign that to something else, not the other way around (which as you stated cannot be done) – RyanS Mar 10 '17 at 18:17
  • 1
    Ha, that's really clever! I know it's a hack, but then again, cancelling a token without a Source calls for a hack. Good work :) – Niels Filter Mar 03 '19 at 21:20
  • Don't forget to call `source.Dispose();` when you are done using it. https://stackoverflow.com/questions/6960520/when-to-dispose-cancellationtokensource – pm.lemay Jul 20 '20 at 17:38
  • *"When given a `CancellationToken`, you can create a new instance of the token source, assign it's token to the provided token, and cancel it."* <== Could you provide an example of this technique? – Theodor Zoulias May 13 '21 at 22:27
19

As an extension of the answers provided so far, if you want to have both a CancellationToken instance provided to your methods, and cancel internally, you should examine CancellationTokenSource.CreateLinkedTokenSource. In essence this will cancel either when cts.Cancel() is called, or one of its supplied tokens is.

Daniel Park
  • 3,773
  • 4
  • 22
  • 37
7

A token gives you the right to know someone is trying to cancel something. It does not give you the right to actually signal a cancellation. Only the cancellation token source gives you that. This is by design.

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
andrew pate
  • 3,301
  • 32
  • 19
2

Spawn CancellationToken instances from a CancellationTokenSource instance and call Cancel on the CTS instance.

Example: Cancel()

There's also a way to gracefully cancel threads without them firing exceptions. Just check the CT for IsCancellationRequested and handle the case yourself.

More information: Use of IsCancellationRequested property?

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
Machinarius
  • 3,467
  • 1
  • 27
  • 50
  • 2
    Then as you are being provided one you are in control of the cancellation. You can either keep tabs on IsCancellationRequested or rely on the framework throwing an exception on your thread to forcibly do so. – Machinarius Jun 16 '15 at 18:49