An exception of type 'System.OperationCanceledException' occurred

user369122 picture user369122 · Dec 14, 2012 · Viewed 11.4k times · Source

I was implementing a Parallel.ForEach loop to do some work, but I bounced into a problem due to an unhandled exception, while I thought I handle the cancellation.

To try and get the finger on the problem, I made a simple test setup in a winform. It has a start button, a cancel button and a label for output.

The code:

public partial class Form1 : Form
{
    CancellationTokenSource cts = new CancellationTokenSource();

    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        output.Text = "Running";

        try
        {
            var runTask = Task<string>.Factory.StartNew(() => Run());
            await runTask;
            this.output.Text = runTask.Result;
        }
        catch(Exception ex)
        {
            throw ex;
        }
    }

    private string Run()
    {
        int useThreads = Environment.ProcessorCount - 2 < 1 ? 1 : Environment.ProcessorCount - 2;

        ParallelOptions options = new ParallelOptions() { MaxDegreeOfParallelism = useThreads, CancellationToken = cts.Token };

        options.CancellationToken.Register(() => ActionOnCancel());

        List<int> somelist =new List<int>();

        for(int i = 0; i < 100; i++)
            somelist.Add(i);

        Parallel.ForEach(somelist, options, (row, loopstate) =>
        {
            if(loopstate.ShouldExitCurrentIteration || loopstate.IsExceptional)
                loopstate.Stop();

            Thread.Sleep(1000);

        });

        return "Done";
    }

    private void ActionOnCancel()
    {
        output.Text= "Cancelled";
    }

    private void button2_Click(object sender, EventArgs e)
    {
        cts.Cancel();
    }

When I run the program and hit the cancel button (to trigger button2_Click), I keep on getting this error:

An exception of type 'System.OperationCanceledException' occurred in mscorlib.dll but was not handled in user code

Additional information: The operation was canceled.

If there is a handler for this exception, the program may be safely continued.

And the debugger highlights the Parallel.ForEach section. But why??? I thought I handled cancellation correct via the CancellationToken.

The exception message in ex doesn't give me any clarity:"{"The operation was canceled."}" uh...yeah....that was the intention...

What am I overlooking? Regards,

Matthijs

Answer

Caleb Keith picture Caleb Keith · Dec 14, 2012

This exception is thrown always. You must handle the OperationCanceledException when accessing the Parallel Tasks if the cancel method is called on the CancellationTokenSource.

try
{
    Parallel.ForEach(somelist, options, (row, loopstate) =>
    {
        if(loopstate.ShouldExitCurrentIteration || loopstate.IsExceptional)
            loopstate.Stop();

        Thread.Sleep(1000);

    });
}
catch (OperationCanceledException)
{
    // Handle the cancelled Task
}