web-dev-qa-db-fra.com

Pourquoi et comment éviter les fuites de mémoire du gestionnaire d'événements?

Je viens juste de réaliser, en lisant quelques questions et réponses sur StackOverflow, que l’ajout de gestionnaires d’événements à l’aide de += en C # (ou, je suppose, dans d’autres langages .net) peut provoquer des fuites de mémoire courantes ...

J'ai utilisé de nombreux gestionnaires d'événements comme celui-ci dans le passé et je ne me suis jamais rendu compte qu'ils pouvaient causer ou avaient causé des fuites de mémoire dans mes applications.

Comment cela fonctionne-t-il (c'est-à-dire, pourquoi cela cause-t-il réellement une fuite de mémoire)?
Comment puis-je résoudre ce problème? Utilise -= assez au même gestionnaire d'événements?
Existe-t-il des modèles de conception communs ou des pratiques recommandées pour gérer de telles situations?
Exemple: comment suis-je censé gérer une application comportant de nombreux threads différents, en utilisant de nombreux gestionnaires d'événements différents pour générer plusieurs événements sur l'interface utilisateur?

Existe-t-il des moyens simples et efficaces de surveiller cela efficacement dans une application volumineuse déjà construite?

149
gillyb

La cause est simple à expliquer: lorsqu'un gestionnaire d'événements est abonné, le éditeur de l'événement contient une référence à abonné via le délégué du gestionnaire d'événements (en supposant que le délégué est un méthode d'instance).

Si l'éditeur vit plus longtemps que l'abonné, il le gardera en vie même lorsqu'il n'y a aucune autre référence à l'abonné.

Si vous vous désabonnez de l'événement avec un gestionnaire égal, alors, le gestionnaire et la fuite éventuelle seront supprimés. Cependant, d’après mon expérience, c’est rarement un problème, car j’aperçois généralement que l’éditeur et l’abonné ont de toute façon une durée de vie à peu près égale.

C'est est une cause possible ... mais d'après mon expérience, il est plutôt sur-excité. Votre kilométrage peut varier, bien sûr ... vous devez juste faire attention.

185
Jon Skeet

Oui, -= est suffisant, cependant, il pourrait être assez difficile de garder une trace de chaque événement assigné, jamais. (pour plus de détails, voir le post de Jon). En ce qui concerne le modèle de conception, jetez un coup d’œil au modèle d’événement faible .

12
Femaref

Un événement est vraiment une liste chaînée de gestionnaires d'événements

Lorsque vous faites + = new EventHandler sur l'événement, peu importe si cette fonction particulière a déjà été ajoutée en tant qu'écouteur, elle le sera une fois par + =.

Lorsque l'événement est déclenché, il parcourt la liste liée, élément par élément et appelle toutes les méthodes (gestionnaires d'événements) ajoutées à cette liste. C'est pourquoi les gestionnaires d'événements sont toujours appelés même lorsque les pages ne sont plus en cours d'exécution tant qu'elles sont affichées. sont en vie (enracinés), et ils seront en vie tant qu'ils sont branchés. Ils seront donc appelés jusqu'à ce que le gestionnaire d'événements soit décroché avec un - = new EventHandler.

voir ici

et MSDN ICI

3
TalentTuner