线程(任务)中的异常不会像示例所暗示的那样传播
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 不会在正确的线程上引发异常