ContinueWith a cancelled Task

2019-02-21 23:46发布

问题:

I have defined the following Task

var t = Task.Factory.StartNew(
    () => LongRunningMethod( cancellationToken ),
    cancellationToken
);

t.ContinueWith(
    Callback,
    cancellationToken,
    TaskContinuationOptions.None,
    TaskScheduler.FromCurrentSynchronizationContext()
);

Inside the LongRunningMethod, I check if the cancellation token has a cancellation requested, and if so, I return from the method. That much works fine.

However, the Callback does not get called in this scenario. The callback does get called if I replace the second line above with

t.ContinueWith(
    x => Callback( x, cancellationToken ),
    TaskScheduler.FromCurrentSynchronizationContext()
);

In this situation, the task still thinks it ran to completion.

Why doesn't the first call work? I was under the impression that TaskContinuationOptions.None means that the callback will get called regardless of the state of the thread.

I am cancelling the Task by calling:

_cancellationTokenSource.Cancel();

On a somewhat related note, having to pass around cancellation tokens seems like a major design flaw of the Task library.

回答1:

Your continuation task takes a CancellationToken which you cancel. This means that the continuation task, while unstarted, is being cancelled. Don't pass that token to thing which you don't want to cancel.

CancellationToken is meant to cancel the whole graph of actions at once. You can exclude stuff from cancellation by not passing the token.