2009-05-29 6 views
5

Dans une classe, ClassA, j'ai un objet timer. Dans cette classe, j'inscris les gestionnaires d'événements pour l'événement écoulé par minuterie. Dans une autre classe, ClassB, j'ai un gestionnaire d'événements public pour l'événement écoulé par minuterie. Donc j'enregistrer le gestionnaire d'événements de classe B en ClassA comme suit:Que se passe-t-il lorsqu'un événement se déclenche et tente d'exécuter un gestionnaire d'événements dans un objet qui n'existe plus?

myTimer.Elapsed += ClassBInstance.TimerElapsed 

Et si je devais créer une nouvelle instance de ClassBInstance et l'événement se déclenche écoulé de la minuterie lorsque l'instance précédente de gestionnaire d'événements de classe B est encore lié à l'événement Elapsed du timer?

Par exemple:

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

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

Répondre

10

AFAIK, ClassBInstance est pas des déchets collectés aussi longtemps que il y a des événements enregistrés, parce que l'événement est titulaire d'une référence.

Vous devez vous assurer de désenregistrer tous les événements des instances qui ne sont plus utilisées.

Important dans les cas où l'instance enregistrée est IDisposable, car l'événement peut être déclenché lorsque l'instance est éliminée. Dans ce cas, j'ai trouvé plus facile de laisser l'instance s'enregistrer elle-même et de la désenregistrer dans Dispose.

+5

En effet. En particulier, c'est la raison pour laquelle les événements statiques sont si dangereux; il est très facile de garder un grand nombre d'objets en vie si vous ne vous désinscrivez pas religieusement. Au moins les événements d'instance meurent avec l'instance qui contient le champ de sauvegarde - mais pas de GC pour la statique. –

+0

Il est également intéressant de mentionner que WPF saute à travers les cerceaux pour éviter cela avec WeakEvents qui sont à mon humble avis trop compliqués et ont besoin d'un soutien linguistique. – Josh

2

Si l'instance précédente est toujours active et que la nouvelle instance a également connecté un gestionnaire d'événements, l'événement déclenchera les deux gestionnaires (un à la fois). Lorsque vous associez des gestionnaires d'événements à des événements, il est important de garder une trace de ces événements. Vous devez également les détacher lorsqu'ils ne sont plus nécessaires. Sinon, les anciennes instances continueront à vivre en mémoire, en exécutant des gestionnaires d'événements susceptibles d'entraîner des résultats inattendus.

3

Les événements sont mis en œuvre de sorte que tant que votre éditeur est en vie, tous les abonnés seront maintenus en vie par l'éditeur même si vous ne détenez aucune autre référence à ceux-ci.

Bien sûr, cela implique également que vous devez détacher les abonnés, si vous voulez qu'ils soient nettoyés indépendamment de l'éditeur.

0

Vous pouvez utiliser mon WeakEventHandler, basé sur WeakReference. Comme il garde une faible référence à l'écouteur d'événement, il ne force pas l'écouteur à vivre.

see this answer