Cancelling a task within a task

c#, task, task-parallel-library

Solution

A task is only considered "cancelled" if

- Its cancellation token is cancelled before it starts executing.

- Its cancellation token is cancelled while it is executing and the code cooperatively observes the cancellation by throwing the OperationCancelledException (usually by the code calling `cts.Token.ThrowIfCancellationRequested()`)

If you added a `cts.Token.ThrowIfCancellationRequested()` line after the `cts.Cancel()` then things would behave as you expect. In your example, the cancellation takes place while the task is running, but the task doesn't observe the cancellation, and the task's action runs to completion. So the task is marked as "Ran to Completion".

You can check for the case of a task that "Ran to Completion" but was cancelled (either during or after the completion of the task) by checking the cancellation token within the continuation (`cts.Token.IsCancellationRequested`). Another option that sometimes helps is to use the original cancellation token as the cancellation token for the continuation (that way, if the the cancellation is not noticed by the antecedent task, it will at least be respected by the continuation)--since the TPL will mark the continuation as cancelled before it even has a chance to run.

Problem

I am trying to cancel a Task<> by calling the CancellationTokenSource.Cancel() method within the task, but I cannot get it to work. Here is the code I am using: ``` TaskScheduler ts = TaskScheduler.Current; CancellationTokenSource cts = new CancellationTokenSource(); Task t = new Task( () => { Console.WriteLine( "In Task" ); cts.Cancel(); }, cts.Token ); Task c1 = t.ContinueWith( antecedent => { Console.WriteLine( "In ContinueWith 1" ); }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ts ); Task c2 = c1.ContinueWith( antecedent => { Console.WriteLine( "In ContinueWith 2" ); }, TaskContinuationOptions.NotOnCanceled ); t.Start(); Console.ReadKey(); Environment.Exit( 1 ); ``` This print outs: ``` In Task In ContinueWith 1 In ContinueWith 2 ``` What I expected was this: ``` In Task ``` Am I missing something here? Can tasks only be cancelled outside of the task?

Original source

Related problems