c# - 即使使用 CriticalFinalizerObject,也不会在未处理的异常后调用终结器

标签 c# .net finalizer

我有这样的测试代码:

public class A : CriticalFinalizerObject 
{
    ~A()
    {
        File.WriteAllText("c:\\1.txt", "1z1z1");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        throw new Exception();
    }
}

首先,我尝试在不从 CriticalFinalizerObject 派生 A 的情况下运行它。此程序结束后未调用终结器。 这让我感到惊讶,因为我认为它更具确定性但还可以。然后我阅读了有关 CriticalFinalizerObject 的信息,这些对象确保将调用它们的终结器。我从中得出 A。 你猜怎么了。它仍然没有被执行。 我在做什么/理解错了什么?

(请不要写关于垃圾收集器不确定的明显内容,我知道。情况并非如此,因为程序结束了,我想我可以在一个很好的未处理托管 异常。)

最佳答案

首先,我们来了解一下MSDN中的CriticalFinalizerObject ,我们可以读到:

In classes derived from the CriticalFinalizerObject class, the common language runtime (CLR) guarantees that all critical finalization code will be given the opportunity to execute, provided the finalizer follows the rules for a CER, even in situations where the CLR forcibly unloads an application domain or aborts a thread.

这里的主要词是UNLOAD

其次,让我们阅读MSDN再次,这次是关于托管线程中的异常:

If these exceptions are unhandled in the main thread, or in threads that entered the runtime from unmanaged code, they proceed normally, resulting in termination of the application.

主要词是TERMINATION

因此,当主线程中存在未处理的异常时 - 应用程序终止,但 CriticalFinalizerObject 仅有助于卸载域。

例如,CriticalFinalizerObject 可以在这种情况下提供帮助:

// Create an Application Domain:
AppDomain newDomain = AppDomain.CreateDomain("NewApplicationDomain");

// Load and execute an assembly:
newDomain.ExecuteAssembly(@"YouNetApp.exe");

//Unload of loaded domain
AppDomain.Unload(newDomain);

在这种情况下,域已卸载,CriticalFinalizerObject 向您保证,您的终结器将被调用。

在您终止应用程序的情况下,您可以尝试订阅

AppDomain.CurrentDomain.UnhandledException

并手动完成您的对象。

更新: Jeffrey Richter 在他的书“CLR via C#”中写到 CriticalFinalizerObject,它适用于将代码发送到 SQLServer 的情况,SQLServer 可以将 C# 作为过程运行。在这种情况下,CriticalFinalizerObject 可以帮助您清理对象,如果 SQLServer 将卸载您的库的域。 此外,CriticalFinalizerObject 适用于您需要在对象的终结器中调用另一个对象的方法的情况,因为 CriticalFinalizerObject 向您保证,它的终结器将在所有非 CriticalFinalizerObject 对象的终结器之后调用。

关于c# - 即使使用 CriticalFinalizerObject,也不会在未处理的异常后调用终结器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10656107/

相关文章:

.net 引用特定版本是真是假?

java - 是内存泄漏吗?为什么 java.lang.ref.Finalizer 吃掉这么多内存

c# - .net sql 异常处理 - 如何获取 sp 参数/值

c# - TraceSource 和 ASP.NET : Works for Web Applications, 不是网站

.net - 为 POINT postgresql 数据类型(或非原始类似 nhibernate 类型的任何 COLUMN)实现新的 NHibernate 类型

c# - 接口(interface)是否兼容多态性

.net - SqlConnection 会被 GC 处理掉吗?

java - 输出最终对象的 JVM 选项

c# - 如何找到所有静态构造函数?

c# - 我的 Blazor 服务器应用程序在一台本地计算机上的 Azure B2c 登录中遇到空引用错误,但在另一台本地计算机上却没有,有什么想法吗?