0

我试图弄清楚 c# 中的 GC/终结器是如何工作的,所以我编写了以下程序。但是在 ReadKey 之后,终结器被调用了 36193 次。我认为它应该在程序完成并且 AppDomain 正在卸载时只调用一次。我在这里缺少什么,这是如何工作的?

    private class GCAnalyzer
    {
        private static int count = 0;
        ~GCAnalyzer()
        {
            if (!AppDomain.CurrentDomain.IsFinalizingForUnload())
            {
                count++;
                GC.ReRegisterForFinalize(this);
                Console.WriteLine("GC " + count);
            }
        }
    }

    static void Main(string[] a)
    {
        new GCAnalyzer();

        Console.ReadKey();
    }
4

2 回答 2

2

如果我没看错,那么当对象“未链接”时您正在调用 ~GCAnalyzer(),并且在该代码期间,您说它还没有准备好通过 GC.ReRegisterForFinalize(this) “取消链接”,这意味着下次检查它仍然没有使用,它的结束代码正在运行......重新注册自己......等等。

于 2013-04-08T12:48:18.537 回答
0

关键是添加 !Environment.HasShutdownStarted 检查。然后在每个集合上调用终结器并将其放回终结列表中。所以在这个程序中,终结器被调用了 3 次。每个 GC.Collect 两次,然后将其注册回最终列表中,第三次当应用程序关闭然后它没有重新注册,因此它可以优雅地关闭 dowb。

    private class GCAnalyzer
    {
        private static int count = 0;
        ~GCAnalyzer()
        {
            Console.WriteLine("GC " + count);
            if (!AppDomain.CurrentDomain.IsFinalizingForUnload() &&!Environment.HasShutdownStarted)
            {
                count++;
                GC.ReRegisterForFinalize(this);                    
            }
        }
    }

    static void Main(string[] a)
    {
        new GCAnalyzer();

        Console.ReadKey();

        GC.Collect();

        Console.ReadKey();

        GC.Collect();
    }
于 2013-04-09T08:27:51.827 回答