AlexandruC
AlexandruC

Reputation: 3637

Asynchronously abort C# TPL Tasks

Is there a way to asynchronously abort C# TPL Tasks created with Task.Factory.Create(() => {stuff}); ? I have seen that there is a way of doing it using a CancellationToken but I like to avoid checking with IsCancellationRequested.

Upvotes: 0

Views: 419

Answers (2)

Honza Brestan
Honza Brestan

Reputation: 10947

EDIT: Updated for .NET 4.5 and newer, details at the bottom of the post.


The CancellationToken is the thing you want to use. Checking the IsCancellationRequested may look like a pain, but it provides a clean way to handle the cancellation, as opposed to creating a thread, then aborting it and having to handle thread aborted exception in the whole code that is being run in parallel.

var cts = new CancellationTokenSource();
var token = cts.Token;
var task = Task.Run(() =>
{
    // Do Job Step 1...
    if (token.IsCancellationRequested)
    {
        // Handle cancellation here, if necessary.

        // Thanks to @svick - this will set the Task status to Cancelled
        // by throwing OperationCanceledException inside it.
        token.ThrowIfCancellationRequested();
    }
    // Do Job Step 2...
    // ...
}, token);

// Later, to kill all the tasks and their children, simply:
cts.Cancel();

It may add some clutter to the delegate, but the cancellation itself is so easy that I never needed to use anything cruder than the cancellation token source. You haven't said why you'd like to avoid it, so unless there is some hard limitation, I'd stick with cancellation tokens.


As per @ipavlu's comment, for a simple use case like this, it's much better to use Task.Run instead of the original Task.Factory.StartNew to fire off the asynchronous work. They provide the same basic functionality, but Task.Run has safer defaults and better support for newer async features, while Task.Factory.StartNew can be used to specify advanced behavior. More info for example here: https://blogs.msdn.microsoft.com/pfxteam/2011/10/24/task-run-vs-task-factory-startnew/

Upvotes: 8

Dan Bryant
Dan Bryant

Reputation: 27495

Cancellation can be difficult to implement, but that's mainly because cancellation, like parallel processing in general, is complicated. You almost certainly don't want to allow aborting at arbitrary points in your code, as this creates almost as many new possible boundary cases to test as there are lines of your code in your asynchronously executed method. This is the kind of nightmare scenario that leads to rare crashes in the wild that are almost impossible to reproduce.

Part of designing your asynchronous process is deciding where it's safe to cancel and how it should deal with cancellation. This may also mean identifying blocking API calls you make (such as network I/O) and calling the appropriate methods to interrupt these blocking operations. It takes a lot of up-front design effort to properly support cooperative cancellation, but, if the feature is required, the up-front investment will more than pay off in reduced headaches later. It does mean, though, that you want to be conservative when budgeting for cancellation as a feature, since it's rarely as simple as it sounds.

Upvotes: 7

Related Questions