2009-05-29 4 views
5

1つのクラス、ClassAに、私はタイマーオブジェクトを持っています。このクラスでは、タイマ経過イベントのイベントハンドラを登録します。 ClassBという別のクラスでは、タイマー経過イベント用のパブリックイベントハンドラがあります。次のようにだから私はにClassAにClassBのからイベントハンドラを登録します。ClassBののイベント・ハンドラの前のインスタンスがまだあるとき、私はClassBInstanceの新しいインスタンスとタイマ経過イベントが発生を作成した場合はどうなりますイベントが発生し、存在しなくなったオブジェクトのイベントハンドラを実行しようとするとどうなりますか?

myTimer.Elapsed += ClassBInstance.TimerElapsed 

タイマーのElapsedイベントに結びついていますか?例えば

ClassB classBInstance = new ClassB(); 
myTimer.Elapsed += classBInstance.TimerElapsed 

classBInstance = new ClassB(); 
myTimer.Elapsed += classBInstance.TimerElapsed 

答えて

10

私の知る限り、ClassBInstanceであれば、イベントがそれへの参照を保持しているため、登録されたイベントがあるようにガベージコレクションではありません。

これ以上使用されていないインスタンスのすべてのイベントを登録解除する必要があります。

重要なのは、インスタンスが破棄されたときにイベントが発生する可能性があるため、登録済みのインスタンスがIDisposableである場合です。この場合、インスタンスを登録してDisposeで登録を解除するのが最も簡単だとわかりました。

+5

実際。特に、これは静的イベントが非常に危険な理由です。あなたが宗教的に登録を解除しなければ、膨大な数のオブジェクトを生かしておくことは非常に簡単です。少なくともインスタンスイベントは、バッキングフィールドを保持するインスタンスではなくなりますが、静的なGCはありません。 –

+0

WPFがWeakEventsを使用してこれを回避するには、IMHOが複雑すぎるし、言語サポートが必要な場合もあることに言及する価値があります。 – Josh

2

以前のインスタンスがまだアクティブで、新しいインスタンスもイベントハンドラを接続している場合、イベントは両方のハンドラを(1度に1つずつ)トリガします。イベントハンドラをイベントにアタッチするタイミングを把握し、イベントハンドラが不要になったときにイベントハンドラを切り離すことが重要です。そうしないと、古いインスタンスはメモリ内に存続し、予期しない結果につながるイベントハンドラを実行します。

3

イベントは、パブリッシャが有効な限り、他の参照を保持していなくても、パブリッシャによってすべてのサブスクライバがアクティブに保たれるように実装されています。

もちろん、これは、サブスクライバをパブリッシャとは独立してクリーンアップしたい場合は、サブスクライバを切り離す必要があることを意味します。

0

WeakReferenceに基づいて私のWeakEventHandlerを使用することができます。イベントリスナーへの弱い参照を保持するため、強制的にリスナーを存続させることはありません。

see this answer

関連する問題