218 votes

Que je devrais DataTable et DataSet Dispose() ?

DataSet et DataTable à la fois de mettre en œuvre IDisposable, donc, par les méthodes classiques de meilleures pratiques, je dois appeler leur Dispose() méthodes.

Cependant, de ce que j'ai lu jusqu'à présent, DataSet et DataTable n'ont pas réellement de toutes les ressources non managées, afin d'en Disposer() ne fait pas beaucoup.

De Plus, je ne peut pas utiliser using(DataSet myDataSet...) parce que DataSet est une collection de tables de données.

Donc, pour être sûr, j'aurais besoin d'itérer myDataSet.Des Tables, de disposer de chacune des tables de données, puis les disposer de l'ensemble de données.

Alors, vaut-il la peine d'appeler dispose() sur tous mes jeux de données et les tables de données?

Addendum:

Pour ceux d'entre vous qui pensent que le jeu de données doivent être éliminés: En général, le motif d'élimination est d'utiliser using ou try..finally, parce que vous voulez vous assurer que Dispose() sera appelée.

Cependant, cela devient laid réelle rapide pour une collection. Par exemple, que faites-vous si l'un des appels à Éliminer() levée d'une exception? Avez-vous avaler (ce qui est "mauvais"), de sorte que vous pouvez continuer à disposer l'élément suivant?

Ou, suggérez-vous que je viens de l'appeler myDataSet.Dispose(), et d'oublier concernant la façon de disposer les tables de données dans myDataSet.Les Tables?

167voto

DOK Points 21175

Voici un couple de discussions expliquant pourquoi Jeter n'est pas nécessaire pour un jeu de données.

Pour Disposer ou de ne Pas les Jeter ? "La méthode dispose en DataSet n'existe que parce que des effets secondaires de l'héritage-- en d'autres termes, il ne fait pas faire quelque chose d'utile dans la finalisation."

Jetez-être appelé sur DataTable et objets DataSet? comprend une explication à partir d'un MVP: "le système de.les données de l'espace de noms (ADONET) ne contient pas de les ressources non managées. Par conséquent, il n'est pas nécessaire de disposer l'un de ceux que longtemps que vous n'avez pas ajouté de vous-même quelque chose de spécial."

La compréhension de la méthode dispose et des ensembles de données? avec comm:ent de l'autorité Scott Allen: "En pratique, nous avons rarement Disposer d'un jeu de données car il offre peu d'avantages"

Ainsi, le consensus est qu' il n'y a actuellement aucune bonne raison de l'appeler Jeter sur un jeu de données.

138voto

Nariman Points 3484

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/

27voto

Nuno Points 129

Vous devez le considérer fait quelque chose d’utile et appel Dispose même si elle ne fait rien en courant. NET des incarnations du cadre, il n’y a aucune garantie, qu'il va rester comme ça à l’avenir les versions menant à l’utilisation inefficace des ressources.

18voto

dwieczor Points 121

Même si l’objet n’a aucune ressource non managée, élimination pourrait aider GC en brisant les graphiques d’objets. En général, si l’objet implémente IDisposable puis Dispose() doit être appelée.

Que Dispose() ne fait quelque chose ou pas dépend de données classe. Dans le cas de DataSet, implémentation Dispose() est héritée de MarshalByValueComponent. Elle supprime lui-même de conteneur et l’événement Disposed appels. Le code source est ci-dessous (démonté avec .NET Reflector) :

9voto

Michael Stum Points 72046

Ne vous créez les tables de données vous-même? Parce que le parcours des enfants de n'importe quel Objet (comme dans un jeu de données.Les Tables) n'est généralement pas nécessaire, comme c'est le travail de la Mère à éliminer tous les membres enfant.

En général, la règle est: Si vous avez créé et qu'il met en œuvre IDisposable, de la Jeter. Si vous n'avez PAS le créer, alors ne les jetez PAS, c'est l'emploi de l'objet parent. Mais chaque objet peut avoir des règles spéciales, consultez la Documentation.

Pour .net 3.5, il dit explicitement "en Disposer lorsque vous n'utilisez pas plus", c'est ce que je ferais.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X