Qu'advient-il si je ne suis pas d'appel dispose sur le stylo d'objet?
Ce qui se passe si je ne l'appelez pas Dispose
sur le pen
objet dans cet extrait de code?
private void panel_Paint(object sender, PaintEventArgs e)
{
var pen = Pen(Color.White, 1);
//Do some drawing
}
- Rien. C'est pourquoi vous devriez l'appeler.
- Il me semble que la documentation MSDN sur ce que la méthode n'est assez clair. msdn.microsoft.com/en-us/library/...
- Eh bien, je suppose que je pourrais avoir formulé la question de ce qui ne se produit pas si je ne l'appelez pas
Dispose
, mais je crois que vous comprenez ce que je veux dire? - Une meilleure question est, pourquoi ne voulez-vous pas de l'appeler Dispose()? Si j'avais écrit cela, je le mettrait dans une instruction d'utilisation.
- Je sais que je suis censé appeler dispose, j'essaie de comprendre pourquoi. Si c'est si important que je l'appelle, pourquoi n'est-il pas fait automatiquement?
- .net ne fait pas échapper à l'analyse. Ainsi, il ne sait pas si la référence survit après
pen
est hors de portée. Ainsi, vous devez attendre jusqu'à ce que le GC décide de recueillir lePen
qui pourrait être beaucoup plus tard. - Et pour les objets qui font partie d'un objet graphique(ce n'est pas le cas pour
Pen
) l'objet peut être maintenu en vie par quelques références qui sont supprime uniquement si vous disposez de l'objet. - pourquoi n'est-il pas fait automatiquement? "Quand serait-il "l'appeler automatiquement" ??! Comment le cadre de déterminer le moment de l'appeler.. c'est à vous, le programmeur... et c'est pourquoi la langue concepteurs ont ajouté la
using
mot-clé, pour vous permettre de spécifier quand à appeler sans avoir à écrire explicitement un appel à elle... - Brinck: je sais que ce n'est pas la réponse à votre question. C'est pourquoi il n'était pas une réponse, mais un jeu de mots dans un commentaire. Même si je pense que le terme correct est "truisme" plutôt que de "sarcasme". Ou, peut-être, "wiseassery" - comme dans ce commentaire 😉
- Si vous êtes trop paresseux pour type
myobj.Dispose()
, vous devez emballer votre code avec un [using
énoncé](msdn.microsoft.com/en-us/library/yh598w02(v=VS.80).aspx. - Ce n'est pas juste de la paresse depuis que vous aviez besoin d'utiliser
try
...finally
d'exception de sécurité et le code est plus difficile à lire qu'à l'aide deusing
. - Aller en prison. Aller directement à la prison. Ne passez pas aller, ne recueillent pas 200 dollars.
- Le problème est que parfois vous ne pouvez pas utiliser "utiliser", par exemple lorsque votre classe doit contenir les champs de non géré type.
Vous devez vous connecter pour publier un commentaire.
La
Pen
seront recueillies par le GC à un moment indéterminé dans l'avenir, si oui ou non vous appelerDispose
.Cependant, toutes les ressources non managées détenus par la plume (par exemple, un RIB+ poignée) ne seront pas nettoyés par le GC. Le GC seulement nettoie les ressources gérées. L'appel de
Pen.Dispose
vous permet de vous assurer que ces ressources non gérées sont nettoyés en temps opportun et que vous n'êtes pas des fuites de ressources.Maintenant, si le
Pen
a un finaliseur et que finaliseur nettoie les ressources non managées, puis les ressources non managées sera nettoyée lors de laPen
est des ordures collectées. Mais le fait est que:Dispose
explicitement afin que vous libérer de vos ressources non managées, etPen
implémenteIDisposable
.IDisposable
est de disposer des ressources non managées. C'est le modèle dans les .NET.Pour les commentaires précédents sur ce sujet, voir ce réponse.
Quelques corrections doivent être faites ici:
Concernant la réponse de Phil Devaney:
En fait, l'appelant Dispose() n'est pas de façon déterministe de provoquer un GC collection .NET - c'est à dire qu'il ne déclenche PAS un GC immédiatement simplement parce que vous avez appelé Dispose(). Seulement indirectement des signaux à la GC que l'objet peut être nettoyé au cours de la prochaine GC (pour la Génération dont l'objet réside dans). En d'autres termes, si l'objet réside dans Gn 1, alors il ne serait pas éliminés jusqu'à ce qu'un Gn 1 collecte. L'un des seuls moyens (mais pas le seul) que vous pouvez par programmation et la conception déterministe de la cause de la GC pour effectuer une collection est en appelant GC.Collect(). Cependant, cela n'est pas recommandé puisque le GC "tunes" lui-même au cours de l'exécution par la collecte de statistiques sur vos allocations de mémoire lors de l'exécution de votre application. L'appel de GC.Collect() vidages de ces mesures et les causes de la GC pour commencer sa "mise au point" une fois de plus.
Concernant la réponse:
C'est incomplète. Comme le gouvernement du canada est non-déterministe, le Modèle dispose, (Comment mettre correctement en œuvre le modèle dispose), est disponible de sorte que vous pouvez libérer les ressources que vous utilisez - gérés ou non. Il a rien à faire avec ce genre de ressources qui vous sont releasing. La nécessité de la mise en œuvre d'un outil de finalisation n'ont à voir avec ce genre de ressources que vous utilisez - savoir mettre en œuvre un si vous avez de la non-finalisable (c'est à dire natif) des ressources. Peut-être que vous confondez les deux. BTW, vous devriez éviter de mettre en œuvre un outil de finalisation par l'aide de la SafeHandle classe à la place qui enveloppe de ressources autochtones qui sont recueillis par P/Invoke ou COM Interop. Si vous finissez par la mise en œuvre d'un outil de finalisation, vous devriez toujours mettre en œuvre le Modèle dispose.
Une critique remarque que je n'ai pas vu personne mentionner encore, c'est que si jetables objet est créé et il a un Finaliseur (et vous ne jamais vraiment savoir si elles le font, et vous avez certainement ne devriez pas faire d'hypothèses à ce sujet), elle sera directement envoyé à la File d'attente de Finalisation et de vivre pendant au moins 1 supplémentaire GC collection.
Si GC.SuppressFinalize() n'est pas en fin de compte appelée, le finaliseur pour l'objet sera appelé sur le prochain GC. Notez qu'une bonne mise en œuvre du modèle dispose devriez appeler GC.SuppressFinalize(). Ainsi, si vous appelez dispose() sur l'objet, et il a mis en œuvre le modèle correctement, vous permettra d'éviter l'exécution de l'outil de finalisation. Si vous n'appelez pas Dispose() sur un objet qui a un finaliseur, l'objet aura sa Finaliseur exécuté par le GC sur la collection suivante. Pourquoi est-ce mauvais? Le Finaliseur fil dans le CLR jusqu'à et y compris .NET 4.6 est mono-thread. Imaginez ce qui se passe si vous augmentez le fardeau sur ce fil - votre les performances de l'application va vous savez où.
Appeler dispose sur un objet contient les éléments suivants:
Modifier:
Je viens de remarquer que le "tout en sachant et est toujours correct" de la documentation MSDN sur IDisposable (extrême sarcasme ici) en fait ne dit
Que tout le monde devrait savoir, MSDN est loin d'être correct, ne mentionne jamais ou montre des "meilleures pratiques", parfois fournit des exemples qui ne compile pas, etc. Il est regrettable que cela est décrit dans ces mots. Cependant, je sais ce qu'ils essayaient de le dire: dans un monde parfait, le GC nettoyage de tous les géré ressources pour vous (comment idéaliste); il ne sera pas, cependant nettoyage non géré ressources. C'est absolument vrai. Cela étant dit, la vie n'est pas parfaite et il n'est ni n'importe quelle application. Le GC ne de nettoyage de ressources qui n'ont pas enracinée références. C'est principalement là où se trouve le problème.
Parmi environ 15-20 façons différentes .NET peut "fuite" (ou pas gratuit) de la mémoire, celle qui seraient le plus susceptibles de vous mordre si vous ne faites pas appel Dispose() est le fait de se désinscrire/décrocher/unwire/détacher des gestionnaires d'événement/délégués. Si vous créez un objet qui a des délégués filaire et vous n'appelez pas Dispose() (et ne pas détacher les délégués à vous-même), le GC va toujours voir l'objet comme ayant enracinée références à - dire les délégués. Ainsi, le GC ne sera jamais le recueillir.
@joren commentaire/question ci-dessous (ma réponse est trop long pour un commentaire):
J'ai un blog sur le modèle dispose je recommande d'utiliser - (Comment mettre correctement en œuvre le modèle dispose). Il ya des moments où vous devez null références et il ne fait jamais de mal de le faire. En fait, cela ne le faire quelque chose avant le GC s'exécute - il supprime la référence enracinée de cet objet. Le GC analyses ultérieures sa collection de enraciné références et recueille ceux qui n'ont pas de référence enracinée. Pense de cet exemple, il est bon de le faire: vous avez une instance de type "ClassA" - appelons-le "X". X contient un objet de type "ClassB" - appelons cela "Y". Y implémente IDisposable, donc, X devrait faire de même à jeter Y. supposons que X est dans la Génération 2 ou la liturgie des heures et Y est dans la Génération 0 ou 1. Lorsque dispose() est appelée sur X et que la mise en œuvre des valeurs null référence de Y, la référence enracinée de Y est immédiatement supprimé. Si un GC qui se passe pour la génération 0 ou Gn 1, la mémoire/des ressources pour Y est nettoyé mais la mémoire/des ressources pour X n'est pas depuis X vit dans Gen 2 ou la liturgie des heures.
this.Foo.Dispose(); this.Foo = null;
alors il n'a pas d'importance siFoo.Dispose
les valeurs null de ses références ou pas, car il n'est plus un chemin de la GC, les racines de l'objet, de toute façon. Si vous êtes seulement à l'aide de Disposer de références nulles, alors vous pourriez aussi bien ne pas utiliser de Disposer à tous et tout simplement se débarrasser de la référence à l'objet directement. Donc MSDN que l'utilisation principale est de libérer des ressources non managées est vrai, puisque tout le reste peut être aussi bien réalisé, sans elle, aussi longtemps que vous ne vous accrochez pas à des références à des objets que vous n'utilisez pas.Le sous-jacent GDI+ stylet poignée ne sera pas libéré jusqu'à ce qu'une période indéterminée, dans l'avenir, c'est à dire lorsque le Stylet objet est nettoyée et le finaliseur de l'objet est appelé. Cela peut ne pas être jusqu'à la fin du processus, ou il peut être plus tôt, mais le point est non-déterministe. Appeler dispose vous permet de faire le nettoyage déterministe et est fortement recommandé.
Le montant total de .Net de la mémoire dans l'utilisation de la .Net part + toutes les données en cours d'utilisation. OS des objets, ouvrir des fichiers, base de données et toutes les connexions réseau de prendre certaines ressources qui ne sont pas purement .Net des objets.
Graphique utilise des Stylos et d'autres objets qui sont en fait des OS, des objets qui sont "très" cher de garder autour. (Vous pouvez échanger votre Stylet pour une 1000x1000 fichier bitmap). Ces OS que les objets sont supprimés de la mémoire du système d'exploitation une fois que vous avez d'appeler un fonction de nettoyage. Le Stylo et le Bitmap de Disposer des fonctions de le faire pour vous immédiatement lorsque vous les appelez.
Si vous n'appelez pas la Jeter à la poubelle collecteur en viendra à nettoyer, " quelque part dans le futur*'.
(Il se fait appeler le destructeur/finaliser le code que probablement appelle dispose())
*sur une machine avec un nombre infini de mémoire (ou de plus de 1 GO), quelque part dans l'avenir peut-être très loin dans le futur. Sur une machine à ne rien faire, il peut être facilement plus de 30 minutes pour nettoyer cette énorme bitmap ou très petite plume.
Si vous voulez vraiment savoir comment c'est quand vous n'appelez pas Jeter sur des objets graphiques, vous pouvez utiliser le CLR Profiler, disponible gratuitement pour le téléchargement ici. Dans le dossier d'installation (par défaut C:\CLRProfiler ) est CLRProfiler.doc qui a un bon exemple de ce qui se passe lorsque vous ne l'appelez pas Jeter sur une Brosse objet. Il est très éclairant. Vous pouvez aussi lire sur l'utilisation de IDisposable ici et ici.
Va conserver les ressources jusqu'à ce que le garbage collector il nettoie
Component
mettre en œuvre un outil de finalisation d'appelDispose
. Le finalizer est non-déterministe, ce qui signifie que vous ne pouvez pas prédire quand elle fonctionne, mais il sera toujours courir par la suite. Si un autre finaliseur bloque indéfiniment, ou que le processus est tué alors bien sûr, il ne sera pas exécuté.Dépend si elle met en œuvre finaliseur et il appelle les Disposer sur sa méthode finalize. Si oui, la poignée sera publié au GC.
si pas, poignée rester autour jusqu'à ce que le processus est terminé.
Graphique avec des trucs il peut être très mauvais.
Ouvrez le Gestionnaire des Tâches de Windows. Cliquez sur "sélectionner les colonnes" et choisissez colonne appelée "Objets GDI".
Si vous ne mettez pas au rebut de certains objets graphiques, ce nombre va continuer d'augmenter et de sensibilisation.
Dans les anciennes versions de Windows, cela peut faire planter l'ensemble de l'application (limite était de 10000 comme je me souviens bien), ce n'est pas sûr Vista/7, mais c'est toujours une mauvaise chose.
GDI+
utilisationGDI
objets? Autant que je sache, WinForms utilise GDI+ et pas GDI pour la plupart de ses fonctionnalités.Dispose
ing d'eux quand il était lui-mêmeDispose
d; (2) la création de stylos toujours à la demande et de ne jamais le cache d'eux; (3) ayant un mondialDictionary<Color, Pen>
qui dure aussi longtemps que la demande, ou (4) avoir un mondialDictionary<Color, WeakReference>
qui tiendrait uneWeakReference
à chaque stylo?WeakReference
approche semble avoir un certain mérite également dans les cas où un contrôle de la tenue d'un objet graphique dans un domaine, mais de nombreux contrôles peut vouloir organiser le même (donc le nombre de contrôles en tenant un objet particulier peut varier de quelques centaines à zéro).le garbage collector permettra de recueillir de toute façon, MAIS c'est important QUAND:
si vous ne vous appelez dispose d'un objet que vous ne l'utiliser vivent plus longtemps en mémoire et sera promu à la hausse des générations, ce qui signifie que la collecte, il a un coût plus élevé.
dans le dos de mon esprit la première idée est venue à la surface, c'est que cet objet sera détruit dès la fin de l'exécution de la méthode!, je ne sais pas où j'ai eu cette info!, est-il juste?