如何在未处理的任务异常上崩溃?

Posted

技术标签:

【中文标题】如何在未处理的任务异常上崩溃?【英文标题】:How to crash on unhandled Task exception? 【发布时间】:2022-01-17 14:22:19 【问题描述】:

我想正确理解在没有异常处理的情况下未能观察到Task 上抛出的异常的后果,并且忘记了异常处理方式。

下面是 Jeffry Richter 的 C# 第三版 CLR 的摘录:“[...] 当 Task 对象被垃圾回收时,它的 Finalize 方法会检查 Task 是否遇到未观察到的异常; 如果有,TaskFinalize 方法会抛出[异常]。由于您无法捕获 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 对原始帖子的评论。

以上是关于如何在未处理的任务异常上崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用原生崩溃报告在 Swift 4 中实现异常/错误处理?

如何强制 WCF 线程中未处理的异常使进程崩溃?

程序崩溃后如何挂起所有线程?

如何在未标记的数据上微调 BERT?

如何实现全局 iPhone 异常处理?

从完成处理程序/块中引发自定义异常会使目标 c 中的应用程序崩溃