Canceling long running task

 26-Apr-2014   nityaprakash     TPL    Comments  0

When long running task is under process, this is a good idea of providing cancellation feature. However it is bit odd but still a useful feature. For example in windows copy process is running in different thread but User Interface provide a feature to cancel the copy process.

Creating cancellable task

To be able to cancel a running task we have to pass CancellationToken object to the task, and call Cancel() method of the token.

  • Create object of CancellationTokeSource object.
  • Get Token property of the CancelationTokenSource object.
  • Pass this token to the task.

Passing CancellatioinToken with Lambda expression


        static void Main(string[] args)
        {

            CancellationTokenSource tokenSource = new CancellationTokenSource();
            CancellationToken token = tokenSource.Token;

            Task task = new Task(() =>
            {
                try
                {
                    for (int i = 0; i < 100; i++)
                    {
                        Thread.Sleep(1000);

                        if (token.IsCancellationRequested)
                        {
                            Console.WriteLine("Canceling the task...");
                            throw new OperationCanceledException(token);
                        }
                        else
                        {
                            Console.WriteLine("Counter :{0}", i);
                        }
                    }
                }
                catch (OperationCanceledException ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }, token);

            task.Start();

            Console.WriteLine("Main method is completed.  Please enter to finish.");
            Console.WriteLine("Please press enter to cancel the task");
            Console.ReadLine();
            tokenSource.Cancel();

            Console.ReadLine();
        }

We have to check CancellationToken.IsCancellationRequested property and throw OperationCanceledException exception it order to tell run time that cancellation is requested. This code only necessary if we want to perform some task like releasing unmanaged resources be fore it throw OperationCanceledException. But if there is nothing to di before cancellation the task we can call token.ThrowIfCancellationRequested() method.

Passing CancellationToken object to method

Below code snippet shows, how to pass method in a long running method.


        static void Main(string[] args)
        {

            CancellationTokenSource tokenSource = new CancellationTokenSource();
            CancellationToken token = tokenSource.Token;

            Task task = new Task((obj) =>PrintMessage(obj), token, token);

            task.Start();

            Console.WriteLine("Main method is completed.  Please enter to finish.");
            Console.WriteLine("Please press enter to cancel the task");
            Console.ReadLine();
            tokenSource.Cancel();

            Console.ReadLine();
        }

        static void PrintMessage(object obj)
        {
            CancellationToken token = (CancellationToken)obj;
            try
            {
                for (int i = 0; i < 100; i++)
                {
                    Thread.Sleep(1000);

                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("Canceling the task...");
                        throw new OperationCanceledException(token);
                    }
                    else
                    {
                        Console.WriteLine("Counter :{0}", i);
                    }
                }
            }
            catch (OperationCanceledException ex)
            {
                Console.WriteLine(ex.Message);
            }

        }

Output:

In above both examples we are enclosing entire code in try/catch block to handle the exception thrown during cancellation request. It is important if we are waiting this task to complete using Task.Wait() method.

If the code is using Task.Wait() method and OperationCanceledException is not handled in long running task it will throw System.AggregationException.

Why Polling

In these examples we are using for loops to check every time whether the Cancellation request raised or not. Cancel can't occur at any stage of code execution. If we want to make cancellable, we have to check for cancellation request after every smallest unit of task which doesn't corrupt application state. It may be loop or sequential steps. It is most important part of creating cancellable task.

Summary

This example shows basic way of creating cancellable task. if we are using parameterized method to pass in Task, we can pass token as stateobject. We should check for Token.IsCancellationRequested after every logical unit finish in the task.


Nitya Prakash Sharma has over 10 years of experience in .NET technology. He is currently working as Senior Consultant in industry. He is always keen to learn new things in Technology and eager to apply wherever is possible. He is also has interest in Photography, sketching and painting.

My Blog
Post Comment

COMMENTS