2009-05-29 2 views
5

In einer Klasse, ClassA, habe ich ein Timer-Objekt. In dieser Klasse registriere ich die Event-Handler für das abgelaufene Timer-Ereignis. In einer anderen Klasse, ClassB, habe ich einen öffentlichen Event-Handler für das abgelaufene Timer-Event. So melde ich das Event-Handler von ClassB in KlasseA wie folgt:Was passiert, wenn ein Ereignis ausgelöst wird und versucht, einen Event-Handler in einem Objekt auszuführen, das nicht mehr existiert?

myTimer.Elapsed += ClassBInstance.TimerElapsed 

Was passiert, wenn ich eine neue Instanz von ClassBInstance und der Timer abgelaufen-Ereignis ausgelöst zu schaffen waren, als die vorherige Instanz ClassB Veranstaltungs-Handler noch ist an das Elapsed-Ereignis des Timers gebunden?

Zum Beispiel:

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

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

Antwort

10

AFAIK ist ClassBInstance nicht Müll gesammelt, solange es Ereignisse registriert, weil das Ereignis einen Verweis auf sie hält.

Sie müssen sicherstellen, dass Sie alle Ereignisse von Instanzen aufheben, die nicht mehr verwendet werden.

Wichtig ist, dass die registrierte Instanz IDisposable ist, da das Ereignis ausgelöst werden kann, wenn die Instanz verworfen wird. In diesen Fällen fand ich es am einfachsten, die Instanz sich registrieren zu lassen und die Registrierung in Dispose aufzuheben.

+5

In der Tat. Aus diesem Grund sind statische Ereignisse besonders gefährlich. Es ist sehr einfach, eine große Anzahl von Objekten am Leben zu erhalten, wenn Sie sich nicht religiös abmelden. Mindestens Instanzenereignisse sterben mit der Instanz, die das Unterstützungsfeld enthält - aber kein GC für Statik. –

+0

Es ist auch erwähnenswert, dass WPF springt durch Reifen, um dies mit WeakEvents zu vermeiden, die IMHO sind zu kompliziert und benötigen einige Sprachunterstützung. – Josh

2

Wenn die vorherige Instanz noch aktiv ist und die neue Instanz ebenfalls einen Ereignishandler angeschlossen hat, löst das Ereignis beide Handler aus (jeweils einzeln). Es ist wichtig zu verfolgen, wenn Sie Ereignishandler an Ereignisse anhängen, die Sie auch trennen, wenn sie nicht mehr benötigt werden. Andernfalls werden die alten Instanzen weiterhin im Speicher vorhanden sein und Event-Handler ausführen, die zu unerwarteten Ergebnissen führen können.

3

Ereignisse werden so implementiert, dass, solange Ihr Publisher noch aktiv ist, alle Abonnenten vom Publisher am Leben erhalten werden, auch wenn Sie keine weiteren Verweise darauf haben.

Natürlich bedeutet dies auch, dass Sie Abonnenten trennen müssen, wenn Sie unabhängig vom Herausgeber aufgeräumt werden wollen.

0

Sie könnten meinen WeakEventHandler basierend auf WeakReference verwenden. Da er einen schwachen Verweis auf den Ereignis-Listener beibehält, zwingt er den Hörer nicht zum Leben.

see this answer