Canceling an Asynchronous Task

Tuesday, January 22, 2019

By: Chris Dunn

When we have a long running operation, it nice to have the option to cancel the operation.  Luckily when they designed the TASK they gave developers the ability to more cleanly exit long running operations.  A TASK is part of the task based asynchronous pattern, which is the suggested pattern moving forward.  With this pattern they have included the idea of a CancellationToken which allows us to signal to a running TASK, that is should cancel.

In the following example I've written a simple console application with a single running task that just writes to the console.  Pressing the space bar key will cause the task to be cancelled.  Here is the entire program, which I will go through a section at a time.

using System.Threading;
using System.Threading.Tasks;
    class Program
    {
        static void Main(string[] args)
        {
            //task will run until spacebar pressed.
            Console.WriteLine("Press spacebar to cancel task.");

            //create a cancellation token source and set token so task
            //can be cancelled.
            var cts = new CancellationTokenSource();
            var token = cts.Token;
            
            //execute asyncronous task passing in cancel token.
            Task.Run(() =>
            {
                //continue executing task until token is set to cancelled.
                while (!token.IsCancellationRequested)
                {
                    Console.WriteLine("Doing Something...");
                    Thread.Sleep(2500);
                }

            }, token);
            

            //loop until spacebar pressed.
            while(true)
            {   
                //check if keypress is available on input stream
                if(Console.KeyAvailable)
                {
                    //check if key press was spacebar
                    Console.WriteLine("Checking if keypress was spacebar.");
                    if(Console.ReadKey(true).Key == ConsoleKey.Spacebar)
                    {
                        //set cancellation token to cancel
                        Console.WriteLine("Task Canceled.");
                        cts.Cancel();
                        break;
                    }
                }
            }

            //finish off the app console
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();

        }
    }

In the first section, we are giving instructions about the space bar. Then we are creating a CancellationTokenSource from which we can create a CancellationToken. The CancellationToken is what we passed as a parameter to the Task.Run in the next section. This allows us to "talk" to the Task to let it know our command to cancel.

         //task will run until spacebar pressed.
            Console.WriteLine("Press spacebar to cancel task.");

            //create a cancellation token source and set token so task
            //can be cancelled.
            var cts = new CancellationTokenSource();
            var token = cts.Token;

Here we are executing the Task. As you can see the first parameter is the function itself that we want to run, and the second parameter is the CancellationToken. Inside the task function we are continually checking if a cancellation of the token has been requested. If not, we continue the execution of our operation.

 //execute asyncronous task passing in cancel token.
            Task.Run(() =>
            {
                //continue executing task until token is set to cancelled.
                while (!token.IsCancellationRequested)
                {
                    Console.WriteLine("Doing Something...");
                    Thread.Sleep(2500);
                }

            }, token);

This section lives outside of the TASK. Here we are looping indefinitly until a key (specifically the space bar) has been pressed. The Console.KeyAvailable is checking if a keypress is sitting in the input stream. If it is, we are reading it in to identify which key was actually pressed. If the key turns out to be the space bar, we call the Cancel method on the CancellationTokenSource we declared in the first section. Doing so will notify the CancellationToken, passed to the TASK run that we are requesting to cancel the task.

 //loop until spacebar pressed.
            while(true)
            {   
                //check if keypress is available on input stream
                if(Console.KeyAvailable)
                {
                    //check if key press was spacebar
                    Console.WriteLine("Checking if keypress was spacebar.");
                    if(Console.ReadKey(true).Key == ConsoleKey.Spacebar)
                    {
                        //set cancellation token to cancel
                        Console.WriteLine("Task Canceled.");
                        cts.Cancel();
                        break;
                    }
                }
            }

And that's about it. A very simple example but enough to show you how to cancel a task.

Tags: c# task asynchronous threads

Copyright 2019 Cidean, LLC. All rights reserved.

Proudly running Umbraco 7. This site is responsive with the help of Foundation 5.