Can I immediately dispose of a CancellationTokenSource after setting it to "Cancel"?

If I start a task with a cancellation token, and I later set the cancellation token to "Cancel", can I then immediately dispose of the cancellation token, or do I need to wait for the task to get the "Cancel" message first?

It's appearing as if I don't need to wait for the task to get the "Cancel" message. It seems to get it anyway:
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
mytask = Task.Run(async () => await MyEndlessTaskLoop(token), token);

...
// Then later in a button click event:
cts.Cancel();
cts.Dispose();

Open in new window

Do I need to insert a wait between the "Cancel()" and "Dispose()"?
cts.Cancel();

try {
    mytask.Wait();
}
catch (AggregateException e) {
   // Expect e.InnerException to be "OperationCanceledException"
}

cts.Dispose();

Open in new window


Also do I need to insert an await in front of Task.Run(...)?
mytask = await Task.Run(async () => await MyEndlessTaskLoop(token), token);

Open in new window


And, is there a difference between passing the cancellation token as a parameter as opposed to just using it as a captured variable? As in:
private async Task MyEndlessTaskLoop()
{
    while(True)
    {
        ...
        this.token.ThrowIfCancellationRequested;
    }
}

Open in new window

vs.:
private async Task MyEndlessTaskLoop(CancellationToken token)
{
    while(True)
    {
        ...
        token.ThrowIfCancellationRequested;
    }
}

Open in new window

Is one preferred over the other?
deleydAsked:
Who is Participating?
 
ste5anSenior DeveloperCommented:
Do I need to insert a wait between the "Cancel()" and "Dispose()"?
No. But CancellationTokenSource implements IDisposable, thus you should either use using, when possible. Otherwise I would call Dispose() in the same scope where the token source was created. But Dispose() calls imho Cancel implicitly.

Also do I need to insert an await in front of Task.Run(...)?
No. await is for the .NET built-in asynchronous method handling. Using Task.Run() is explicit parallel code. An await on Task.Run() would only wait until the threads are started. There is no need for this.

Instead of this.token.ThrowIfCancellationRequested; use CancellationToken.IsCancellationRequested property as a more defensive way of doing it.

[..]difference between passing the cancellation token as a parameter as opposed to just using it as a captured variable[..]
Well, the difference is that the variable could be changed from the outside. Especially it could be set to null. This is not possible with passed token.
0
 
deleydAuthor Commented:
Thank you!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.