从 Parallel.ForEach 抛出未处理的 OperationCanceledException

Posted

技术标签:

【中文标题】从 Parallel.ForEach 抛出未处理的 OperationCanceledException【英文标题】:Unhandled OperationCanceledException when thrown from Parallel.ForEach 【发布时间】:2012-09-15 11:03:20 【问题描述】:

我正在尝试允许取消 Parallel.ForEach 循环。根据this MSDN article的说法是有可能的,我正在关注他们的编码。

// 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);

但是,当我从用户可访问的函数中调用 cts.Cancel(); 时,应用程序在上面标有星号的行上崩溃并出现错误:

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: 

我有异常处理程序,所以我不理解崩溃。有什么想法吗?

【问题讨论】:

我没有看到您描述的问题,catch 对我来说很好用。您能否发布一个完整但简短的代码来显示您的问题? 我认为应用程序没有崩溃,至少没有这个例外。要么你的应用没有崩溃(你怎么知道它已经崩溃了?),或者这不是最后一个发生的异常。 @usr 是的,你是对的。我在调试器中运行它,当我看到异常停止运行时,我认为这是一个会使应用程序崩溃的异常。我不知道有些异常不会导致崩溃。 我相信这通常被称为第一次机会例外。正如您所注意到的,这并不意味着它会使应用程序崩溃,而只是一个调试概念。 【参考方案1】:

问题在于po.CancellationToken.ThrowIfCancellationRequested(); 明确抛出了一个未处理的异常。异常处理程序可能在 Parrallel.ForEach() 调用附近,但异常不在 lambda 表达式中处理。删除该行或在 lambda 表达式中添加一个异常处理程序,它应该可以工作。

更多信息请参见Cancelling a Task is throwing an exception。

【讨论】:

@svick 可能。看看我链接的答案并尝试它的建议。如果它有效,它就有效。 @akton:我尝试将 try/catch 放在 Lamba 表达式中,但仍然会导致运行时错误。 @Doug 嗯。我会继续挖掘,如果我找到任何东西,我会告诉你。提出问题,看看是否有其他人知道 @akton 我能够通过在 lambda 表达式中使用 try/catch 并将 Parallel.ForEach 包装在 try/catch 中来解决此问题。不知道为什么我必须同时做这两件事。 @publicENEMY 对ThrowIfCancellationRequested() 的调用进行尝试/捕获。

以上是关于从 Parallel.ForEach 抛出未处理的 OperationCanceledException的主要内容,如果未能解决你的问题,请参考以下文章

ExpressJS - 抛出未处理的错误事件

PeekMessage() 抛出未处理的异常(访问冲突)

在 TPL 中快速抛出未处理的异常

Xcode升级后iOS项目抛出未处理的异常

抛出未处理的异常:读取访问冲突。 x 是 0x20B4112

Visual Studio 2019 c++latest random_device uniform_int_distribution 抛出未处理的异常