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?
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.