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 ごとに 2 回、ファイナライズ リストに登録し直します。

    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 に答える