线程(任务)中的异常不会像示例所暗示的那样传播

Posted

技术标签:

【中文标题】线程(任务)中的异常不会像示例所暗示的那样传播【英文标题】:Exception in thread (Task) is not propagated like example suggests 【发布时间】:2019-10-20 22:55:47 【问题描述】:

示例代码来自“C# 7.0 in a nutshell”,第 580 页:

        Task task = Task.Run(() =>  throw null; );
        try
         
            task.Wait(); 
        
        catch (Exception ex)
         

在我的 VS2017 中执行,并没有按照书中描述的方式工作。 从 IDE 内部运行,System.NullReferenceException 立即在第一行抛出(并停止执行),而该示例表明异常在启动的线程内抛出并在那里等待直到有人调用 Wait() 或读取 @987654325 @ 在Task 对象上。在第 277 页上,对Task 类进行了简要说明,并且对 可以使用线程池 的提及非常不清楚。我想在我的情况下它没有被使用,而是主线程正在执行 lambda,因此会生成一个未捕获的异常。我找不到有关如何或在何处配置线程池或Task 类的行为的提示。还是我错过了一些完全不同的东西?

【问题讨论】:

无法重现:dotnetfiddle.net/nUyWwO(或在 VS2017 或 VS2019 中)。你确定你不会因为调试器在抛出异常时中断而感到困惑吗? 是的,您可能会看到调试器突出显示了 lambda,因此它恰好与您的 Task.Run 在同一行,如果您检查堆栈跟踪,您可能应该在其中看到 task.Wait() @canton7 你是对的,从 IDE 外部开始,代码的行为与建议的一样。嗯,这似乎在调试时使事情变得复杂...... 我认为它的 GUI 有点不同,它应该只是突出显示的行的一部分或让您区分的东西,但 stacktrace 应该始终正确 @IlyaChernomordik 不,我认为调试器会在抛出一个未处理的异常后立即停止整个应用程序。 【参考方案1】:

您很可能在抛出异常时看到调试器中断

这里的赠品是对话框显示“抛出异常”,throw 语句以黄色突出显示。

默认情况下,当您的代码中的任何异常被抛出时,调试器将中断,无论它后来是否被捕获(或者,如果您禁用了“仅我的代码”,当任何地方抛出任何异常时)。

您可以通过单击对话框中的“打开异常设置”链接或转到“调试”->“Windows”->“异常设置”并取消选中“通用语言运行时异常”来更改此设置。

您还可以准确控制调试器将中断哪些异常。在“抛出异常”对话框中,您还可以取消选中“抛出此异常类型时中断”复选框,以停止调试器在将来中断该异常类型。

当您意识到要重新启用对默认异常集的中断时,异常设置顶部有一个方便的重置按钮:

【讨论】:

以上是关于线程(任务)中的异常不会像示例所暗示的那样传播的主要内容,如果未能解决你的问题,请参考以下文章

使用异步方法等待 Task.Run 不会在正确的线程上引发异常

LCG 在 Kolmogorov-Smirnov 测试中是不是像我的代码所暗示的那样严重失败?

Java多线程之捕获子线程中的异常---面试经

为啥在这个多线程示例中没有捕获到异常?

C# 中的异常未按预期运行

异常传播和 std::future