2010-04-13 3 views
5

Dites que j'ai deux classes, et aucun d'entre eux sont des composants GUI. La classe A est un court objet vécu qui enregistre un événement déclarée par un objet B. Par exemple vécu longtempsAi-je besoin de Disposer pour annuler les événements?

public A(B b) 
{ 
    b.ChangeEvent += OnChangeEvent; 
} 

Si A ne désinscrit de l'événement B, A sera jamais ordures collectées? A a-t-il besoin d'une méthode Dispose pour se désinscrire de l'événement de B?

Il existe également une deuxième question connexe. Si A et B doivent tous les deux vivre pendant toute la durée d'exécution de l'application, A doit-il se désinscrire?

Répondre

3

À votre première question: Oui. B a une référence à A. De cette façon, A va vivre aussi longtemps que B. C'est une bonne façon de perdre de la mémoire dans une application de l'interface utilisateur si vous p. inscrivez-vous avec un événement comme App.OnIdle.

À la seconde: À la fin tout sera tué.

0

Si B contient une référence à A, A ne récupérera pas de place à moins que B ne soit également éligible pour la récupération de place.

Vous ne devriez pas avoir besoin d'une méthode Dispose pour cela. Une fois que B n'a aucune référence pointant vers lui non plus, le Garbage Collector sera assez intelligent pour éliminer B et A.

S'ils sont tous deux actifs pendant la vie de l'application, vous n'avez pas besoin de désenregistrer l'événement.

+0

... sauf si A est également éligible pour la collecte des ordures. –

+0

Comme Jon a dit, qu'en est-il de A? – Sean

+0

@Sean, j'ai eu B et A inversés. Une fois les références externes retirées de B, A sera également éliminé. – kemiller2002

1

L'emplacement approprié pour déconnecter l'événement serait, comme vous le supposez, dans la méthode IDisposable.Dispose de A. Il n'y a pas vraiment de bonne alternative. Il serait inutile d'essayer de déconnecter l'événement dans le finaliseur/destructeur A, puisque la seule façon dont A serait éligible pour la récupération de place avant sa déconnexion de B serait pour B de devenir lui-même éligible pour la récupération de place; Une fois que cela est arrivé, l'abonnement deviendrait un point discutable, cela n'aurait donc pas d'importance s'il était nettoyé ou non.

Si les événements d'abonnés éphémères abandonnés doivent être nettoyés pendant la durée de vie d'un éditeur de longue durée, il existe des moyens de le faire si les classes de publication et d'abonnement coopèrent. Par exemple, le visage public de l'abonné de l'événement peut être un objet encapsuleur qui contient une référence à l'abonné de l'événement réel, l'abonné lui-même ne disposant pas d'une référence forte à cet objet public. Dans ce scénario, l'abonnement à l'événement n'empêcherait pas l'objet public de tomber hors de la portée et de devenir éligible à la finalisation. Un finaliseur dans l'objet public pourrait informer l'objet abonné que l'abonnement ne serait plus nécessaire et qu'il devrait se désinscrire. Comme une telle notification arriverait de manière asynchrone, l'objet publiant l'abonnement devrait offrir un moyen par lequel les abonnés pourraient se désabonner de manière asynchrone. Cela pourrait être fait par une requête "unsubscribe" normale, à condition que l'événement de publication le garantisse non-bloquant et thread-safe; Malheureusement, la plupart des événements n'offrent pas cette garantie.

Questions connexes