Je viens de donner une réponse à un Question assez simple < / a> en utilisant une méthode d'extension. Mais après l'avoir écrit, je me suis souvenu que vous ne pouvez pas vous désabonner d'une Lambda d'un gestionnaire d'événements. Jusqu'à présent, pas de gros problème. Mais comment tout cela se comporte-t-il dans une méthode d'extension ?? p> ci-dessous est mon code reniflé à nouveau. Alors, quelqu'un peut-il vous éclairer, si cela conduira à des myriades de minuteries suspendues à la mémoire si vous appelez cette méthode d'extension plusieurs fois plusieurs fois? P> Je dirais non, car la portée de la minuterie est limitée dans cette fonction . Donc, après avoir laissé cela, personne d'autre n'a une référence à cet objet. Je suis juste un peu incertain, car nous sommes ici dans une fonction statique dans une classe statique. P> juste pour clarifier j'ai utilisé System.windows.Forms.ticer . Donc, de vos réponses, il semble que, notamment en utilisant cette classe de minuterie, était le bon choix parce que cela fait quelque chose comme je l'attends dans ce cas. Si vous essayez une autre classe de minuterie dans ce cas, vous pouvez rencontrer des ennuis comme Matthew a découvert .
Aussi je trouvé un moyen en utilisant mise à jour h3>
Après un peu de sommeil et un peu plus de pensée, j'ai également fait un autre changement à mon testeur ( Réponse ci-dessous ) Je viens d'ajouter un Donc, après toutes vos bonnes réponses et un peu plus de tests, je peux heureusement dire que ça fait Ce qu'il devrait sans laisser de minuteries dans la mémoire ni jeter les minuteries avant de faire leur travail. P> p> gc.collect () code> après la dernière ligne et définissez la durée sur 10000 . Après le démarrage du
BlinkText () Code> Plusieurs fois, j'attends tout le temps ma touche2 pour obtenir l'état actuel et forcer une collection à ordures. Et comme il semble que toutes les chronomètres seront détruits
7 Réponses :
Votre hypothèse est correcte. Le gestionnaire d'événements Lamba (en supposant que ce n'est pas référencé ailleurs) sera également éligible à la collecte des ordures. P>
Le fait qu'il s'agisse d'une méthode statique et / ou d'une méthode d'extension ne modifie pas les règles de base de l'accessibilité de l'objet. P> TIMER code> sera attribué lorsque la méthode est appelée et être éligible à la collecte des ordures à la fin. p>
Cela pourrait-il signifier que si vous appelez GC.Collect avant la durée, cela pourrait entraîner une défaillance clignotante?
@Alxandr: Non, une minuterie active reste accessible, le GC ne le collectera pas.
On dirait que la minuterie restera vivante jusqu'au début du programme. J'ai essayé de disposer de l'étiquette et de définir sa référence à NULL, mais la minuterie n'a pas été collectée avant d'avoir quitté le programme. P>
Compilez pour libérer et forcer une collection.
Je l'ai fait mais ce n'est pas collecté.
Ouais, je me demandais simplement si cela serait nettoyé. Je suppose que le fait que la minuterie soit jetable. Quelque chose doit conserver une référence à l'objet de la minuterie, puis à nouveau, le fil pouvant traiter la boucle d'événement. Il est très possible que l'objet reste de rester en vie parce que la référence de l'événement. Alors oui, il y a beaucoup une fuite ici.
C'est bien de voir que les gens sont toujours en train de voter sans laisser de note.
Les fuites de mémoire ne sont pas votre problème ici. Le collecteur des ordures peut disposer de l'objet de la minuterie. Mais pendant que la minuterie n'est pas arrêtée, il semble y avoir une référence à la minuterie, il n'est donc pas disposé prématurément. Pour vérifier cela, dérivez une classe Mytimer de la minuterie, déverrouiller le dispositif (BOOL) et définir un point d'arrêt. Après un appel de blinktext appel GC.Collect et GC.WAITFORPENDENDINAIRES. Après le deuxième appel, la première instance de minuterie est disposée. P>
Je ne pouvais pas vérifier cela (avec un appel à gc.collect directement après l'appel à Blinktext).
Je viens de faire un test amusant dans le sens de ce que @ Cornerback84 disait. J'ai créé un formulaire avec une étiquette et deux boutons. Un bouton lié votre méthode d'extension, l'autre liaison A Forced Il semble qu'il y a une fuite de mémoire / de ressource ici ... mais à nouveau, la minuterie est un objet jetable qui n'est jamais disposé. p>
EDIT: ... strong> p>
Laissez le plaisir de commencer ... Cela peut également dépendre de la minuterie system.windows.forms.ticer strong> => ceci
ne collectera pas mais va travailler juste
Fine avec la pompe à message système. Si vous appelez system.timers.timer strong> => cela ne fait pas
Utilisez la pompe à message. Vous aussi aussi
appelez la pompe à message. Ce ne sera pas
collecter. Si vous appelez system.threading.Timer strong> => Ceci nécessite d'invoquer la pompe à message. Mais cela s'arrêtera également sur un gc.collect () code>. J'ai ensuite supprimé le
Timer.stop () code> dans votre boucle d'événement. C'était vraiment amusant de cliquer plusieurs fois sur le bouton de démarrage. L'intervalle du clignotement a été assez mélangé. p>
code> que vous utilisez. p>
.stop () code> Cet objet pourrait devenir éligible pour collecter. P> li>
.stop () code> Cet objet pourrait devenir éligible pour collecter. P> li>
gc.collect () code> (cette version ne semblait pas fuir) p> li>
ul>
Ne pas disposer d'un état idéal n'est pas une fuite de mémoire. C'est juste inefficace.
@HENK: Cela peut beaucoup conduire à des fuites de mémoire et de ressources.
Matthew, un malentendu courant. Idisposables dont il a besoin d'avoir un destructeur (finaliseur). Le nettoyage est juste retardé.
@HENK: Le finaliseur n'est jamais appelé si quelque chose dans le système tient une référence à l'objet. Il existe également des objets qui mettent en œuvre Idisposable qui n'ont pas de finaliseurs (grâce aux auteurs de ces classes;). Il est également très possible que votre finisseur ne soit jamais appelé. Il est à 100% du GC de l'appeler. Et s'il n'obtient pas le travail suffisamment rapide, le GC pourrait tuer l'appel.
"Le GC pourrait tuer l'appel" - êtes-vous sûr? Pour le reste, voir
@HENK: Comment cela se rapporte-t-il? Il parlait d'utilisation du en utilisant la déclaration code>. MSDN.MicRosoft.com/en-us/Library/system. objet.finalize.aspx
Vous voudrez peut-être aussi consulter cette question (et ses réponses) Stackoverflow.com/Questtions/45036/...
Votre code est correct et ne fuit pas la mémoire ni les ressources, mais seulement strong> parce que vous arrêtez la minuterie de l'EventHandler. Si vous commencez le La minuterie attribue une fenêtre à écouter pour les messages WM_ et est en quelque sorte ancré par cela. Lorsque la minuterie est arrêtée ( // minuterie.stop (); code> il restera sur clignotant, même lorsque vous faites un
gc.collect (); code> plus tard. P >
activé = false code>), il libère cette fenêtre.
Le statique code> ou
méthode d'extension code> ne joue pas de rôle. P>
Juste parce que vous .STOP () CODE> Les minuteries ne sont pas éliminées par magicide. Le système tient toujours une référence à cet objet même s'il ne fait rien.
Je rétracte ce que j'ai dit. Vous cherchez plus près que system.windows.forms.ticer code> a la possibilité de libérer le gchandle lorsque vous appelez stop.
Vous devez disposer de la minuterie explicitement en appelant sa méthode d'étalage ou implicitement en appelant l'arrêt après l'utilisation, votre implémentation est donc correcte et ne causerait jamais de fuites de mémoire. P>
Après avoir lu toutes vos réponses, je viens de trouver un moyen de mieux le tester.
J'ai mis à jour ma classe d'extension de la manière suivante: p> J'ai aussi créé une seconde Bouton, une deuxième étiquette et ajouté le code suivant à l'événement de clic: p> Je viens de reprocher le premier bouton plusieurs fois pour laisser clignoter la première étiquette. Ensuite, j'ai appuyé mon deuxième bouton et j'ai obtenu une liste où je peux voir si mes minuteries sont toujours vivantes. À un premier clic, ils ont tous un vrai. Mais ensuite, j'ai frappé mon premier bouton plusieurs fois à nouveau et quand j'ai mis à jour mon message d'état, j'ai vu que les premiers articles ont déjà une fausse in Isalive. Donc, je peux dire en toute sécurité que cette fonction ne conduise pas de problèmes de mémoire. P> p>
Votre code échouera sans distinction dû à l'appel de fil croisé illégal. Votre minuterie (spécifiquement le WinForms One) doit avoir un objet de synchronisation.
@Leppie: mal, cette minuterie utilise le messagePump. Essayez-le.
@HENK HOLTERMAN: Merci, il semble que je l'ai confus avec le
system.timers.timer code>.