Mise À Jour (1er Décembre 2009):
Je voudrais modifier cette réponse et de concéder que l'original de la réplique a été entaché d'irrégularités.
L'analyse d'origine ne s'applique à des objets qui nécessitent de finalisation, et le point que les pratiques ne devraient pas être acceptées que sur la surface, sans précision, d'une compréhension en profondeur est toujours debout.
Cependant, il s'avère que les ensembles de données, DataViews, DataTables supprimer la finalisation de leurs constructeurs – c'est pourquoi l'appel Jetez() explicitement ne fait rien.
Sans doute, c'est parce qu'ils n'ont pas les ressources non managées; ainsi, malgré le fait que MarshalByValueComponent constitue des provisions pour les ressources non managées, ces implémentations n'ont pas besoin et ne peut donc renoncer à la finalisation.
(C' .NET, les auteurs prennent soin de réprimer de finalisation sur la très des types qui occupe habituellement le plus de mémoire parle de l'importance de cette pratique, en général, pour finalisable types.)
Nonobstant, que ces détails sont encore sous-documentées depuis la création de l' .NET Framework (presque 8 ans) est assez surprenant (que vous êtes essentiellement de gauche à vos propres appareils tamiser si contradictoires, ambiguës matériau de mettre les morceaux ensemble est parfois un peu frustrant, mais ne fournissent une compréhension plus complète du cadre de notre vie quotidienne).
Après beaucoup de lecture, voici mon interprétation:
Si un objet nécessite de finalisation, il pourrait occuper la mémoire plus que nécessaire – voici pourquoi: a) de Tout type qui définit un destructeur (ou hérite d'un type qui définit un destructeur) est considéré comme finalisable; b) Sur la répartition (avant l'exécution du constructeur), un pointeur est placé sur la file d'attente de Finalisation; c) Un objet finalisable exige normalement 2 collections à être remis en état (au lieu de la norme 1); d) La suppression de la finalisation n'est pas de supprimer un objet de la file d'attente de finalisation (tel que rapporté par !FinalizeQueue dans SOS)
Cette commande est trompeuse; en Sachant ce que sont les objets de la file d'attente de finalisation (en soi) n'est pas utile de Savoir quels objets sont sur la file d'attente de finalisation et nécessitent encore de finalisation serait utile (est-il une commande pour cela?)
La suppression de la finalisation tourne un peu dans l'objet de l'en-tête indiquant le moment de l'exécution, il n'a pas besoin d'avoir son Finaliseur invoquée (n'a pas besoin de se déplacer à la file d'attente FReachable); Il reste sur la file d'attente de Finalisation (et continuent d'être signalés par !FinalizeQueue dans SOS)
La DataTable, DataSet, DataView classes sont toutes enracinées à MarshalByValueComponent, un objet finalisable qui peut (potentiellement) gérer les ressources non managées
- Parce que DataTable, DataSet, DataView de ne pas introduire de ressources non managées, ils suppriment la finalisation de leurs constructeurs
- Alors que c'est une évolution inhabituelle, elle libère de l'appelant d'avoir à vous soucier d'appeler Jeter après utilisation
- Cela, et le fait que les tables de données peuvent être partagées entre différents ensembles de données, est probablement pourquoi les ensembles de données ne se soucient pas de disposer enfant DataTables
- Cela signifie également que ces objets apparaissent sous la !FinalizeQueue de SOS
- Cependant, ces objets doivent toujours être remise en état après une collection unique, à l'instar de leurs homologues finalisable
4 (nouveau références):
Réponse Originale À Cette Question:
Il y a beaucoup de trompeurs et généralement de très mauvaise réponses sur ce point - n'importe qui qui a atterri ici devrait ignorer le bruit et lire les références ci-dessous attentivement.
Sans doute, Jetez doit être appelée sur n'importe quel Finalisable objets.
Les tables de données sont Finalisable.
L'appel de Disposer de manière significative accélère la récupération de la mémoire.
MarshalByValueComponent appels GC.SuppressFinalize(ce) dans sa Dispose() - sauter cela signifie avoir à attendre des dizaines, sinon des centaines de Gen0 collections avant que la mémoire est récupérée:
Avec cette compréhension de base de la finalisation de nous
peut déjà en déduire très important
choses:
Tout d'abord, les objets qui ont besoin de finalisation
vivent plus longtemps que les objets qui ne le sont pas.
En fait, ils peuvent vivre beaucoup plus longtemps.
Par exemple, supposons qu'un objet qui
est dans gen2 doit être finalisé.
Finalisation sera programmée mais le
l'objet est toujours en gen2, de sorte qu'il sera
pas de nouveau être collectées jusqu'à la prochaine
gen2 collection qui se passe. Qui pourrait être
un temps très long, et, en fait,
si les choses vont bien, il sera un
longtemps, parce que gen2 collections
sont coûteux et donc nous voulons qu'ils
arrive que très rarement. Les plus âgés
les objets ayant besoin de finalisation pourrait
avoir à attendre pendant des dizaines si pas
des centaines de gen0 collections avant
leur espace est récupéré.
Deuxièmement, les objets qui ont besoin de finalisation
provoquer des dommages collatéraux. Depuis le
interne pointeurs d'objet doit rester
valide, non seulement les objets
directement avoir besoin de s'attarder sur la finalisation de la
dans la mémoire, mais tout l'objet
renvoie, directement et indirectement,
restera aussi dans la mémoire. Si une énorme
arbre d'objets a été ancré par un
objet unique que nécessaire
la finalisation, la totalité de l'arbre
s'attardent, peut-être pour une longue
le temps que nous venons de discuter. Il est
par conséquent important d'utiliser les finaliseurs
avec parcimonie et de les placer sur des objets
qui ont que peu d'objet interne
les pointeurs que possible. Dans l'arbre
l'exemple que je viens de faire, vous pouvez facilement
éviter le problème en déplaçant le
les ressources sont dans le besoin de la finalisation d'un
séparé de l'objet et de garder un
référence à l'objet dans la racine
de l'arbre. Avec cette modeste changement
le seul objet (on l'espère une belle
petit objet) s'attardent et la
finalisation coût est réduit au minimum.
Enfin, les objets ayant besoin de finalisation
créer du travail pour le finaliseur fil.
Si votre processus de finalisation, est un
complexe, le seul et unique
finaliseur thread va passer
beaucoup de temps à l'exécution de ces étapes,
ce qui peut provoquer un arriéré de travail et
donc causer plus d'objets à la flânerie
en attente de finalisation. Par conséquent,
il est très important que
les finaliseurs faire aussi peu de travail que
possible. Rappelez-vous aussi que, bien que
tous les pointeurs d'objet restent valables
au cours de finalisation, il pourrait être l'
cas que ces pointeurs conduire à
les objets qui ont déjà été
finalisé et donc peut-être moins
que utile. Il est généralement plus sûr de
éviter de suivre des pointeurs d'objet dans
finalisation du code même si l'
les pointeurs sont valides. Un coffre-fort, court
finalisation chemin de code est la meilleure.
Prendre de quelqu'un qui a vu 100s de MBs de non-référencée des DataTables dans Gen2: c'est extrêmement important et a complètement manqué par les réponses sur ce fil.
Références:
1-
http://msdn.microsoft.com/en-us/library/ms973837.aspx
2-
http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entrée
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage-collector-performance-using-finalizedispose-pattern.aspx
3-
http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/