devoured elysium
devoured elysium

Reputation: 105197

OperationCanceledException being thrown in Adam Freeman's Pro Parallel Programming in C#'s examples. Is this a bug or am I missing something?

When running in a Console application under Visual Studio 2012 Listing_07 of Adam Freeman's Pro .NET 4 Parallel Programming in C#, I get an exception when I try to cancel the task. To me there seems to be no big mistery as to the why of this, as we're throwing (or so it seems) a OperationCanceledException when a cancellation attempt is detected in the task.

Is this a bug or am I missing something? The problem is arising in basically all his task cancellation examples! I can only assume something in the Task Library was changed since the book came to the stores (2010) ?

// create the cancellation token source
CancellationTokenSource tokenSource
    = new CancellationTokenSource();

// create the cancellation token
CancellationToken token = tokenSource.Token;

// create the task
Task task = new Task(() => {
    for (int i = 0; i < int.MaxValue; i++) {
        if (token.IsCancellationRequested) {
            Console.WriteLine("Task cancel detected");
            throw new OperationCanceledException(token);
        } else {
            Console.WriteLine("Int value {0}", i);
        }
    }
}, token);

// wait for input before we start the task
Console.WriteLine("Press enter to start task");
Console.WriteLine("Press enter again to cancel task");
Console.ReadLine();

// start the task
task.Start();

// read a line from the console.
Console.ReadLine();

// cancel the task
Console.WriteLine("Cancelling task");
tokenSource.Cancel();

// wait for input before exiting
Console.WriteLine("Main method complete. Press enter to finish.");
Console.ReadLine();

Upvotes: 2

Views: 396

Answers (2)

Matt Smith
Matt Smith

Reputation: 17444

The exception is caught by the TPL, and the Task is put into the Canceled state. So, while you will see the exception (if you have exceptions turned on in the debugger), it will be handled.

As leon mentioned, you should be using the CancellationToken.ThrowIfCancellationRequested method, rather than explicitly doing the check + throw yourself.

This page gives good details on cancellation of Tasks: http://msdn.microsoft.com/en-us/library/dd997396.aspx

Upvotes: 1

leon
leon

Reputation: 772

There is no try catch to silence the exception. It is just thrown when you press enter twice. Isn't it made to behave this way? Wrap it in a try 'n catch and it should be graceful.

                try
                {
                    for (int i = 0; i < int.MaxValue; i++)
                    {
                        if (token.IsCancellationRequested)
                        {
                            Console.WriteLine("Task cancel detected");
                            token.ThrowIfCancellationRequested();
                        }
                        else
                        {
                            Console.WriteLine("Int value {0}", i);
                        }
                    }
                }
                catch(OperationCanceledException e)
                {
                    Console.WriteLine("Task cancelled via token!");
                }

There's also that convenient CancelletionToken.ThrowIfCancellationRequested() method you could use to catch.

Upvotes: 1

Related Questions