CriticalFinalizerObject

CriticalFinalizerObject

我有这样的测试代码:

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 ,我们可以阅读,即:



这里的主要词是 UNLOAD

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



主要词是 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

并手动完成您的对象。

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

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

10-09 04:59