Pourquoi et Comment les éviter Gestionnaire d'Événement fuites de mémoire?
Je viens de réaliser, par la lecture de quelques questions et réponses sur StackOverflow, que l'ajout de gestionnaires d'événements à l'aide de +=
en C# (ou je suppose que, d'autres .net languages) peut provoquer des courants de fuites de mémoire...
J'ai utilisé des gestionnaires d'événement de ce genre dans le passé à de nombreuses reprises, et jamais réalisé qu'ils peuvent causer, ou ont fait, les fuites de mémoire dans mes applications.
Comment cela fonctionne (sens, pourquoi ne ce fait provoquer une fuite de mémoire) ?
Comment puis-je résoudre ce problème ? Est l'aide de -=
pour le même gestionnaire d'événements assez ?
Sont commun des modèles de conception ou de meilleures pratiques pour le traitement des situations de ce genre ?
Exemple : Comment suis-je censé gérer une application qui a de nombreux threads différents, à l'aide de beaucoup de différents gestionnaires d'événements de soulever plusieurs événements sur l'INTERFACE utilisateur ?
Y a la bonne et simple des façons de surveiller efficacement dans un déjà construit de grandes la demande?
Vous devez vous connecter pour publier un commentaire.
La cause est simple à expliquer: tout en un gestionnaire d'événement est souscrit, le éditeur de l'événement contient une référence à l' abonné via le gestionnaire d'événement délégué (en supposant que le délégué est une méthode d'instance).
Si l'éditeur vit plus longtemps que l'abonné, puis il va garder l'abonné en vie, même quand il n'y a pas d'autres références à l'abonné.
Si vous vous désabonnez de l'événement avec un égal gestionnaire, alors oui, qui va supprimer le gestionnaire et la fuite. Cependant, dans mon expérience, c'est rarement un problème - parce que en général, je trouve que l'éditeur et l'abonné ont à peu près égale de la durée de vie de toute façon.
Il est une cause possible... mais dans mon expérience, c'est plutôt surfaite. Votre kilométrage peut varier, bien sûr... vous avez juste besoin d'être prudent.
null
surDispose
et l'a appelé à effacer ces "non géré" des ressources. Peut-être une meilleure façon serait d'appeler les méthodesClearSubscriptions
etClearData
et appelDispose
plus tard, quand je n'ai plus besoin de l'éditeur, avant de GC? Merci pour la réponseDispose
méthode. Réglage de l'événement à null (par l'éditeur) semble être une force brute approche, et je ne la considèrent pas la responsabilité de l'éditeur. Dans le imaginé le scénario, j'aurais l'éditeur exposer un événement,PleaseStopListeningToMe
, et il serait de la responsabilité des abonnés à agir en conséquence.Oui,
-=
est assez, Cependant, il pourrait être très difficile de garder une trace de chaque événement affecté, jamais. (pour le détail, voir Jon post). Concernant le modèle de conception, jetez un oeil à la la faiblesse de l'événement motif.IDisposable
et de se désabonner d'un événement.Un événement est vraiment une liste de gestionnaires d'événements
Lorsque vous n' += new EventHandler sur l'événement qu'il n'a pas vraiment d'importance si cette fonction a été ajoutée en tant qu'auditeur avant de, il sera ajouté une fois par +=.
Lorsque l'événement est déclenché aller dans la liste liée, élément par élément, et d'appeler toutes les méthodes (les gestionnaires d'événements) ajoutés à cette liste, c'est pourquoi les gestionnaires d'événements sont toujours, même quand les pages sont plus en cours d'exécution tant qu'ils sont vivants (enraciné), et ils seront en vie aussi longtemps qu'ils sont branchés. De sorte qu'ils seront appelés jusqu'à ce que le gestionnaire d'événements est décroché avec un -= new EventHandler.
Voir Ici
et MSDN ICI