2017-12-09 17 views
2

イベントハンドラがガベージコレクション操作にどのように影響するかについて完全に混乱しています。イベントハンドラがCLRのガベージコレクションに影響する

オブジェクトがa1のガベージコレクションにより収集されない理由、例えば、(A1のデストラクタを呼び出していない):

デストラクタは、ガベージコレクタによって呼び出されていなくてもtimeChangeなeventHandlerを退会した後。

よろしくお願いいたします。要約する

public class B 
{ 
    private void button1_Click(object sender, EventArgs e) 
    {  
     A a1 = new A(); 
     a1.timeChange += A1_timeChange; 

     a1.Start(); 

     a1 = null; 

     GC.Collect(); 
    } 

    private void A1_timeChange(object sender, EventArgs e) 
    { 
     MessageBox.Show(((DateTime)sender).ToString()); 
    } 
} 

public class A 
{ 
    ~A() 
    { 
     MessageBox.Show("A Collected"); 
    } 

    public void Start() 
    { 
     if (timeChange != null) 
     { 
      Task.Factory.StartNew(() => { 
       while (true) 
       { 
        timeChange(DateTime.Now, null); 
        System.Threading.Thread.Sleep(3000); 
       } 
      }); 
     } 
    } 
    public event EventHandler timeChange; 
} 
+2

このタスクは 'this.timeChange'メンバで参照を保持し、未定義になると悲惨です。 while(true)ループは、それが永遠に参照されていることを保証します。イベントを静的に静的にすると、収集されたイベントが表示されます。 –

答えて

1


それは、これを引き起こすのではなく、クロージャを使用して長い実行中のスレッドからクラスAのインスタンスのメンバを参照した場合、それ自体ではありません。

イベント自体は問題ではありませんか?あなたはすべての参照を処分した場合

ので、クラスBの内側A1_timeChangeを参照するようにイベントpublic event EventHandler timeChangeを実装するクラスA内のデリゲートを引き起こしa1.timeChange += A1_timeChange;このコードは、参照は、あなたのシナリオでは他の方法で回避
ですクラスBに、しかし、Bでのハンドラメソッドを指すAで、イベントハンドラは、到達可能なクラスBを保つことができるイベントから退会ないため、GC'edませんでした、本当に何が起こっている


あなたのクラスAi read more

永遠に実行されているタスクが生成されました(アプリケーションが終了すると停止します。/フォアグラウンドスレッドが終了します)。これは、GCルートの1つからアクセスできます(特に実行中のスレッド)。 )このコード

Task.Factory.StartNew(() => { 
       while (true) 
       { 
        timeChange(DateTime.Now, null); 
        System.Threading.Thread.Sleep(3000); 
       } 

との事はあなたがtimeChangeイベントの上に閉じラムダを使用していること、であり、それは単に

もう一つクラスを参照するクラスを生成するコンパイラを作りますデストラクタ(これはコンパイルされていますファイナライザ)を使用すると、1つのGCコレクションでオブジェクトの存続期間を延ばすことができます。最初のGCでは、オブジェクトは到達不能としてマークされ、ファイナライズキューに配置されます。そして、の次の GCで、ファイナライザは実際に実行されます。 - read more

関連する問題