Cancelling Tasks in .NET 4.0

Posted by: Suprotim Agarwal , on 4/15/2010, in Category .NET Framework
Views: 139285
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.
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:
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.

Absolutely Awesome Book on C# and .NET

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!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
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



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Thai on Sunday, September 30, 2012 12:13 AM
Thanks for your post. It's great.
I assume I have a web server to call to a WCF service to do somethings. The server can send a request to cancel a running task in WCF service.
Can I send a CancellationToken to the WCF service to cancel a task ?

Many thanks,
Thai
Comment posted by Thai on Sunday, September 30, 2012 1:57 AM
Thanks for your post. It's great.
I assume I have a web server to call to a WCF service to do somethings. The server can send a request to cancel a running task in WCF service.
Can I send a CancellationToken to the WCF service to cancel a task ?

Many thanks,
Thai
Comment posted by Himanshu on Tuesday, January 29, 2013 11:43 PM
Hi

From Main Task (t1  like GenerateNumbers)if the method itself generates 'n' number of tasks i.e. GenerateNumbers method having loop generating new tasks from inside. If cancellation of main task is called what will happen to child tasks generated from inside method GenerateNumbers.



Comment posted by Pradeep on Thursday, June 13, 2013 5:01 AM
I found your example to be a bit flawed.
Even though you are breaking from the loop, the t1.IsCanceled is false.
In order to cancel the task, it is recommended to call
cToken.ThrowIfCancellationRequested() in order to update IsCanceled to true.