Can I get CancellationToken
which was passed to Task
constructor during task action executing. Most of samples look like this:
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task myTask = Task.Factory.StartNew(() =>
{
for (...)
{
token.ThrowIfCancellationRequested();
// Body of for loop.
}
}, token);
But what if my action is not lambda but a method placed in other class and I don't have direct access to token
? Is the only way is to pass token
as state?
Yes, in that case, you would need to pass the token boxed as state, or included in some other type you use as state.
This is only required if you plan to use the
CancellationToken
within the method, however. For example, if you need to calltoken.ThrowIfCancellationRequested()
.If you're only using the token to prevent the method from being scheduled, then it's not required.
This seems to work:
This can be necessary to make general-purpose Task helpers preserve the CancellationToken of a cancelled Task (I arrived here while trying to make Jon Skeet's WithAllExceptions method preserve the Token).
When we look at the Task class reference source code we can see that the cancellation token is stored inside an internal class: ContingentProperties
https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Task.cs,90a9f91ffffd80b5cc
The purpose is to avoid the access of these properties and those properties are not always necessary.
No, you can't get it directly from the
Task
object, no.Those are two of the options, yes. There are others though. (Possibly not an inclusive list.)
You can close over the cancellation token in an anonymous method
You can pass it in as state
You can ensure that the instance used for the task's delegate has an instance field that holds onto the cancellation token, or holds onto some object which holds onto the token, etc.
You can expose the token though some other larger scope as state, i.e. as a public static field (bad practice in most cases, but it might occasionally be applicable)
As other answers state, you can pass the token as a parameter to your method. However, it's important to remember that you still want to pass it to the
Task
as well.Task.Factory.StartNew( () => YourMethod(token), token)
, for example.This insures that:
The
Task
will not run if cancellation occurs before theTask
executes (this is a nice optimization)An
OperationCanceledException
thrown by the called method correctly transitions the Task to aCanceled
stateYou can get the CancellationToken by accessing internal fields with reflection.
Hint: You can search for such things on your own with ILSpy .