2009-03-07 6 views
3

ガベージコレクションについて知る方法を見つけようとしています。いずれか、開始、終了、または処理中です。私は実際にコレクション自体に接続されたいくつかのイベントが必要です(私は思っています)。ガベージコレクションが発生したときにアプリケーションに通知するイベントはありますか?

私の問題は、私が最初から書いたWeakEventManagerを持っていて、もはや生きていないWeakReferencesを削除していることです(WeakReferencesは辞書にあります)。

問題は、「クリーンアップする」ときがわかっていることです。コレクターがその作業をしているときには、クリーンアップするのが良いでしょう。ガベージコレクションの後であっても、少なくとも次のコレクションはこれらの古いオブジェクトを削除します。

答えて

4

ここでは、GCが発生したことをSmartInspectに記録するために使用したクラスがあります。このクラスの動作を簡単に変更することができます。

開始するには、GCLog.Register();に電話してください。

#region File Header 
// This file Copyright © 2007 Lasse Vågsæther Karlsen, All rights reserved. 
// 
// $Id: GCLog.cs 135 2008-05-28 11:28:37Z lassevk $ 
#endregion 

#region Using 

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Diagnostics; 
using Gurock.SmartInspect; 

#endregion 

namespace PresentationMode 
{ 
    /// <summary> 
    /// This class is used to get a running log of the number of garbage collections that occur, 
    /// when running with logging. 
    /// </summary> 
    public sealed class GCLog 
    { 
     #region Construction & Destruction 

     /// <summary> 
     /// Releases unmanaged resources and performs other cleanup operations before the 
     /// <see cref="GCLog"/> is reclaimed by garbage collection. 
     /// </summary> 
     ~GCLog() 
     { 
      SiAuto.Main.LogMessage("GARBAGE COLLECTED"); 
      if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted) 
       new GCLog(); 
     } 

     #endregion 

     #region Public Static Methods 

     /// <summary> 
     /// Registers this instance. 
     /// </summary> 
     public static void Register() 
     { 
#if DEBUG 
      if (SiAuto.Si.Enabled) 
       new GCLog(); 
#endif 
     } 

     #endregion 
    } 
} 
+0

これは通常Gen-zeroにしか生き残れないことに注意してください。これは非常に安価なコレクションです(意味はほとんどありません)。通常、人々がGCについて話しているとき、より高価なコレクションに興味があります –

7

.NETメモリのパフォーマンスカウンターオブジェクトを監視できます。ジェネレーション0、1、2のコレクションの数がカウントされます。

一般に、GCベースのシステムでは、GCを直接参照することは、アンチパターンの何かです。 WeakReferenceをクリアして使用しようとすると、あなたは(制限された説明を与えれば)おそらくほんのちょっと綺麗になるでしょう。

+0

+1「クリアしたWeakReferenceを試してみると、怠惰にクリーンアップする方がいいでしょう。」 – configurator

6

System.GCクラスにはRegisterForFullGCNotificationメソッドが用意されています。このメソッドは、ガベージコレクションの実行が完了すると通知が行われるようにします。

このメソッドの使用にはいくつかの注意点がありますが、このメソッドを動作させるには同時ガベージコレクションを無効にする必要があります。

完全な情報については、以下のリンクを参照してください。

Garbage Collection Notifications

GC.RegisterForFullGCNotification Method

+0

しかし、これはwhileループで「待つ」必要がありますか? –

+0

これは本当ですが、これは別のスレッドで行うことができます。私が言ったように、それは理想的ではありませんが、 "ハッピーな"コードに頼らずにガベージコレクタから通知を受け取る "フレームワークに優しい"方法を提供します。 – CraigTP

1

あなたのオブジェクトへの発信参照が、無入ってくる参照しているスローアウェイオブジェクトを作成した場合、すなわち

new MyGcMonitor(this); // don't store result 

MyGcMonitorにFinalizer(デストラクタ)があることを確認したら、そのファイナライザGC faseが完了した後、別のスレッドで呼び出されます。 ファイナライザは、クラスのファイナライズが完了したことを通知するメソッドを呼び出すことができます。

トリッキーな部分は、オブジェクトを解放しない場合など、もう一度必要な場合です。実行中のGCスレッドの外にMyGcMonitorの別のインスタンスを作成するシーケンスをセットアップする必要があります。私はあなたがdelegate.invokeを使用し、その代理人が最初にGC.WaitForPendingFinalizers()を呼び出すことができると思います。

MyGcMonitorを再起動すると、後で(静的な)参照を削除するのと同様の問題が発生します。

0

優先度の低いスレッドでは、この単純な静的メソッドでアプリケーションのクリーニングが必要かどうかを確認できます。

private static bool NeedsCleaning() 
    { 
     if (DummyRef.IsAlive) { 
      return false; 
     } 
     DummyRef = new WeakReference (new object()); 
     return true; 
    }