An exception of type "System.OperationCanceledException" is thrown

I ran a Parallel.ForEach loop to do some work, but I got into a problem due to an unhandled exception while I thought I was handling the cancellation.

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

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 press the cancel button (to start button2_Click), I continue to get this error:

An exception of type "System.OperationCanceledException" occurred in mscorlib.dll, but was not processed in the user code

Additional Information: The operation has been canceled.

If there is a handler for this exception, the program can safely continue.

And the debugger allocates the Parallel.ForEach section. But why??? I thought I reacted correctly to cancellation via a CancellationToken.

The exception message in ex does not give me any clarity: "{" The operation was canceled. "}" Uh ... yes ... that was the intention ...

What am I missing? Yours faithfully,

Matthijs

+4
source share
2 answers

This exception is always thrown. You must handle an OperationCanceledException when accessing Concurrent Tasks if the cancellation method is called in 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 } 
+8
source

CancellationToken.Register () offers a way to add a callback to a cancellation, but does not handle it in terms of an OperationCanceledException.

I suggest you place a try / catch block in the Run () method.

+1
source

All Articles