Cancelling Tasks in .NET 4.0
Posted by: Suprotim Agarwal ,
on 4/15/2010,
in
Category .NET 4.0
Abstract: In one of the previous articles Parallel Tasks in .NET 4.0 (Part II) – Methods that Return value, we used the Task(TResult) class which represents an asynchronous operation that can return a value. In this article, we will see how to cancel a task/operation.
.NET 4.0 introduces a lightweight struct called the CancellationToken that provides a mechanism to cancel synchronous and asynchronous operations. Here are some important members of this struct:
isCancellationRequested - a Boolean property that can be polled by the code to find out if it has been cancelled or the cancellation has been requested
Register - to register a delegate for a callback when a cancellation request has been made
We use an instance of the CancellationTokenSource class to get a cancellation token. What I liked primarily about this Cancellation model is that the cancellation token can be passed freely to the listeners. So cancelling the token is cleanly separated from the ability to consume a request for cancellation. Here are the steps required to cancel a task:
1. We first create the cancellation token(cToken) using the CancellationTokenSource class.
2. The cancelable task(GenerateNumbers) is then created by passing the cancellation token to Task<>.Factory.StartNew().
3. We then use the Register() method to register a delegate(cancelNotification) to notify us when a cancellation request has been made.
4. On pressing 1, the request for a task to be cancelled is made using the CancellationTokenSource.Cancel() method, and the delegate notifies us that the cancellation was requested.
Let us illustrate the steps shown above and understand the process of cancelling a task with the help of an example. The code has comments which explains what’s going on
C#
using System;
using System.Threading.Tasks;
using System.Threading;
namespace CancelTask
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press 1 to cancel task");
var cTokenSource = new CancellationTokenSource();
// Create a cancellation token from CancellationTokenSource
var cToken = cTokenSource.Token;
// Create a task and pass the cancellation token
var t1 = Task<int>.Factory.StartNew(()
=> GenerateNumbers(cToken), cToken);
// to register a delegate for a callback when a
// cancellation request is made
cToken.Register(() => cancelNotification());
// If user presses 1, request cancellation.
if (Console.ReadKey().KeyChar == '1')
{
// cancelling task
cTokenSource.Cancel();
}
Console.ReadLine();
}
static int GenerateNumbers(CancellationToken ct)
{
int i;
for (i = 0; i < 10; i++)
{
Console.WriteLine("Method1 - Number: {0}", i);
Thread.Sleep(1000);
// poll the IsCancellationRequested property
// to check if cancellation was requested
if (ct.IsCancellationRequested)
{
break;
}
}
return i;
}
// Notify when task is cancelled
static void cancelNotification()
{
Console.WriteLine("Cancellation request made!!");
}
}
}
VB.NET (Converted)
Imports System
Imports System.Threading.Tasks
Imports System.Threading
Namespace CancelTask
Friend Class Program
Sub Main(ByVal args() As String)
Console.WriteLine("Press 1 to cancel task")
Dim cTokenSource = New CancellationTokenSource()
' Create a cancellation token from CancellationTokenSource
Dim cToken = cTokenSource.Token
' Create a task and pass the cancellation token
Dim t1 = Task(Of Integer).Factory.StartNew(Function() GenerateNumbers(cToken), cToken)
' to register a delegate for a callback when a
' cancellation request is made
cToken.Register(Sub() cancelNotification())
' If user presses 1, request cancellation.
If Console.ReadKey().KeyChar = "1"c Then
' cancelling task
cTokenSource.Cancel()
End If
Console.ReadLine()
End Sub
Private Shared Function GenerateNumbers(ByVal ct As CancellationToken) As Integer
Dim i As Integer
For i = 0 To 9
Console.WriteLine("Method1 - Number: {0}", i)
Thread.Sleep(1000)
' poll the IsCancellationRequested property
' to check if cancellation was requested
If ct.IsCancellationRequested Then
Exit For
End If
Next i
Return i
End Function
' Notify when task is cancelled
Private Shared Sub cancelNotification()
Console.WriteLine("Cancellation request made!!")
End Sub
End Class
End Namespace
Here’s the output:
This article demonstrated a fairly simple example of cancelling a task. In the forthcoming articles, we will see some more advanced scenarios. The entire source code of this article can be downloaded over here
I hope you liked the article and I thank you for viewing it.
Give me a +1 if you think it was a good article. Thanks!