Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unhandled OperationCanceledException when thrown from Parallel.ForEach

I am trying to allow cancellation of a Parallel.ForEach loop. According to this MSDN article, it is possible, and I am following their coding.

// Tokens for cancellation 
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;

try
{
    Parallel.ForEach(queries, po, (currentQuery) =>
    {
        // Execute query
        ExecuteQuery(currentQuery);

        // Throw exception if cancelled 
        po.CancellationToken.ThrowIfCancellationRequested(); // ***
    }); 
}
catch (OperationCanceledException cancelException)
{
    Console.WriteLine(cancelException.Message);
}

However, when I call cts.Cancel(); from a user-accessible function, the app crashes on the line marked with asterisks above with the error:

System.OperationCanceledException was unhandled by user code
  Message=The operation was canceled.
  Source=mscorlib
  StackTrace:
   at System.Threading.CancellationToken.ThrowIfCancellationRequested()
   at CraigslistReader.SearchObject.<>c__DisplayClass7.<bw_DoWork>b__5(Query currentQuery) in {PATH}:line 286
   at System.Threading.Tasks.Parallel.<>c__DisplayClass2d`2.<ForEachWorker>b__23(Int32 i)
   at System.Threading.Tasks.Parallel.<>c__DisplayClassf`1.<ForWorker>b__c()
InnerException: 

I have the Exception handler right there, so I don't understand the crash. Any ideas?

like image 343
Doug Avatar asked Sep 24 '12 00:09

Doug


People also ask

How do you handle errors in parallel ForEach?

For and Parallel. ForEach overloads do not have any special mechanism to handle exceptions that might be thrown. In this respect, they resemble regular for and foreach loops ( For and For Each in Visual Basic); an unhandled exception causes the loop to terminate as soon as all currently running iterations finish.

How to cancel Parallel ForEach?

Cancel a Parallel. For or Parallel. ForEach loop in . NET by supplying a cancellation token object to the method in the ParallelOptions parameter.

How do you handle exceptions in parallel loops C#?

When you add your own exception-handling logic to parallel loops, each exception should be catched and saved to a list(Use Concurrent Queue), because each loop will create different exception. So after the loop exists we can wrap all exceptions from the list in a System. AggregateException and throw it.


1 Answers

The issue is that po.CancellationToken.ThrowIfCancellationRequested(); is explicitly throwing an exception, which is unhandled. The exception handler may be around the Parrallel.ForEach() call but the exception is not handled within the lambda expression. Either remove the line or add an exception handler within the lambda expression and it should work.

See Cancelling a Task is throwing an exception for more information.

like image 121
akton Avatar answered Sep 22 '22 18:09

akton