Reputation: 3637
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
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
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