如何在未处理的任务异常上崩溃?
Posted
技术标签:
【中文标题】如何在未处理的任务异常上崩溃?【英文标题】:How to crash on unhandled Task exception? 【发布时间】:2022-01-17 14:22:19 【问题描述】:我想正确理解在没有异常处理的情况下未能观察到Task
上抛出的异常的后果,并且忘记了异常处理方式。
下面是 Jeffry Richter 的 C# 第三版 CLR 的摘录:“[...] 当 Task
对象被垃圾回收时,它的 Finalize
方法会检查 Task
是否遇到未观察到的异常; 如果有,Task
的 Finalize
方法会抛出[异常]。由于您无法捕获 CLR 的终结器线程抛出的异常,因此您的进程将立即终止。”
我正在编写一些测试代码来导致终止,但无法导致终止。
使用测试代码here,我可以看到TaskScheduler.UnobservedTaskException
处理程序被调用。但是,如果我注释掉事件处理程序订阅,异常似乎被吞没了,不会导致程序终止。
我已经在版本 4 和 4.8 上使用 .NET Framework 和 Release 版本进行了尝试。
我如何证明未能观察到在 Task
上引发的异常确实会导致崩溃?
【问题讨论】:
您确定您实际上一直在 .NET 4 上运行,而不仅仅是针对 .NET 4 而是在 4.5+ 上运行?根据docs.microsoft.com/en-us/dotnet/api/…,您可以在 app.config 中针对每个应用程序进行配置,但默认设置是不立即使应用程序崩溃。 谢谢@JonSkeet 我想就是这样。添加<ThrowUnobservedTaskExceptions enabled="true"/>
确实会按预期使程序崩溃。
乔恩你有时间在这里发布答案吗?
不,您可以自己添加答案。
【参考方案1】:
Jon Skeet 在他的comment 原帖中正确识别了这个问题。
我找到的关于这个主题的最佳资源是Stephen Toub。
tldr: “为了让开发人员更容易编写基于任务的异步代码,.NET 4.5 更改了未观察到的异常的默认异常行为。虽然未观察到的异常仍会导致引发 UnobservedTaskException 事件(不这样做将是一个重大更改),默认情况下,进程不会崩溃。相反,无论事件处理程序是否观察到异常,异常都会在事件引发后被吃掉。不过,可以配置此行为。新的 CLR 配置标志可用于恢复到 .NET 4 的崩溃行为,例如“
<configuration>
<runtime>
<ThrowUnobservedTaskExceptions enabled=”true”/>
</runtime>
</configuration>
【讨论】:
这看起来是一个很好的参考,谢谢。引用了 Jon 对原始帖子的评论。以上是关于如何在未处理的任务异常上崩溃?的主要内容,如果未能解决你的问题,请参考以下文章