Cancelling Tasks in .NET 4.0
Posted by: Suprotim Agarwal ,
on 4/15/2010,
in
Category .NET Framework
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.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn