.NET 4.0 Cancelling an executing task with a cancellation token

By Indranil Chatterjee

Traditional multi threading in .NET Framework didn't offer a clean way to cancel operations running on a thread. But the CancellationTokenSource class in Task Parallel Library offers a clean way to cancel tasks. This FAQ provides an example to explain that.

Cancelling an operation running on a separate thread wasn't very neat with traditional multithreading. Options like Abort or Suspend were never recommended as they left threads in an inconsistent state. With Task Parallel Library, the CancellationTokenSource class offers a better way to cancel tasks and more importantly, it allows the cancelled tasks to handle and report cancellations in a better way. The following program illustrates how to acheive that in a simple scenario:

using System;
using System.Threading.Tasks;
using System.Linq;
using System.Threading;

namespace ParallelProgramming.TaskPrograms
{
class Program
{
static void Main(string[] args)
{
//Create a cancellation token source, this will be used to cancel a task
var cts = new CancellationTokenSource();
//Create and start a task and pass on the cancellation token to it
var task = Task.Factory.StartNew
(
() =>
//We also pass on the token to the operation for it access the token to check for
//cancellation
DoSomeWork(cts.Token), cts.Token
);

//Wait for user input
if (Console.ReadKey().KeyChar == 'c')
{
//Cancel the task if the user enters the character 'c' (lower case)
Console.WriteLine("Task cancellation requested");
cts.Cancel();
try
{
task.Wait();
}
//Trap AggregateException to catch anyexception thrown by the task
catch (AggregateException ex)
{
ex.InnerExceptions.ToList().ForEach(e => Console.WriteLine("msg: " + e.Message));
}
}
}

//This method contains the operation being executed by the task in parallel
private static void DoSomeWork(CancellationToken token)
{
//Check if cancellation is requested, using the token passed to the method
//This check is for the case when cancellation might have been requested even before start of the
//task
if (token.IsCancellationRequested)
{
Console.WriteLine("Cancelled before start");
//This throws an OperationCanceledException if the token has had cancellation requested
token.ThrowIfCancellationRequested();
}

//This simulates work
Console.WriteLine("Working...");
var sw = new SpinWait();
for (var i = 0; i < 1000; i++)
{
for (int j = 0; j < 50; j++)
{
sw.SpinOnce();
}
//Check for requested cancellation amidst execution logic
if (token.IsCancellationRequested)
{
Console.WriteLine("Cancelling task on request");
//This throws an OperationCanceledException if the token has had cancellation requested
token.ThrowIfCancellationRequested();
}
}
//This code is reached if the task gets to complete prior to a cancellation request
Console.WriteLine("Task completed normally");
}
}
}

.NET 4.0 Cancelling an executing task with a cancellation token  (7579 Views)