TPL cancellation continuation never called on cancelled Task
.net, multithreading, task, task-parallel-library
Solution
Your cancellation continuation is being cancelled because it uses the same cancellation token.
If you think about it it makes total sense: When you say "I want to cancel all processing" you actually get what you ask for. All processing stops, including updating the UI.
The solution is to not use the cancellation token for the cancel, error and `ContinueWhenAny` continuations. That way these continuations always run.
Problem
I have the following setup in my code that utilizes the TPL: - One field in my class: private CancellationTokenSource _cancellationTokenSource; - This CancellationTokeSource gets instatiated every time I create a TPL task that uses that particular cancellationtoken The actualy TPL tasks look like this: ``` var dataRetrievalTask = new Task<List<myType>>(() => { // retrieve data and do something foreach (var a in retrievalMethod()) { if (_cancellationTokenSource.Token.IsCancellationRequested) _cancellationTokenSource.Token.ThrowIfCancellationRequested(); // do something if not cancelled } } return filledListOfMyType; }, _cancellationTokenSource.Token); // define what shall happen if data retrievel finished without any problems var writingLoadedDataToGridTask = dataRetrievalTask.ContinueWith(task => { // do something in case we ran to completion without error }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnRanToCompletion, currentScheduler); // what to do in case cancellation was performed var loadingDataCancelledTask = dataRetrievalTask.ContinueWith(task => { someLabel.Text = "Data retrieval canceled."; },_cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnCanceled, currentScheduler); // what to do in case an exception / error occured var loadingDataFaulted = dataRetrievalTask.ContinueWith(task => { someLabel.Text = string.Format("Data retrieval ended with an Error."); }, _cancellationTokenSource.Token, TaskContinuationOptions.OnlyOnFaulted, currentScheduler); // when any of the continuation tasks ran through, reset ui controls / buttons etc Task.Factory.ContinueWhenAny(new[] { writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted }, task => { // reset controls and all that }, _cancellationTokenSource.Token, TaskContinuationOptions.None, currentScheduler); dataRetrievalTask.Start(); ``` Now my problem is that when the _cancellationTokenSource.Cancel() method is called somewhere (in a Cancel-button's .Click event handler) that particular loadingDataCancelledTask's body/method isn't called. What am I doing wrong here? I am using and handing over the same _cancellationTokenSource.Token instance... and everything else (the 'writingLoadedDataToGridTask' and 'loadingDataFaulted' tasks & the following 'Task.Factory.ContinueWhenAny(new[] { writingLoadedDataToGridTask, loadingDataCancelledTask, loadingDataFaulted }, task => ...' block) do actually work. Only cancellation does not. Does anyone see/know why?