Question

DataSet et DataTable à la fois mettre en œuvre IDisposable, donc, par les pratiques traditionnelles, je devrais appeler leurs méthodes Dispose ().

Cependant, d'après ce que je l'ai lu jusqu'à présent, DataSet et DataTable ne sont pas réellement des ressources non gérées, doit donc être éliminé () ne fait pas beaucoup.

De plus, je ne peux pas simplement utiliser using(DataSet myDataSet...) parce DataSet a une collection de DataTables.

Alors, pour être sûr, je dois itérer myDataSet.Tables, disposer chacun des DataTables, puis jetez le DataSet.

Alors, est-il vaut pas la peine d'appeler Dispose () sur tous mes DataSets et DataTables?

Addendum:

Pour ceux d'entre vous qui pensent que DataSet doit être mis au rebut: En général, le schéma de disposition est d'utiliser using ou try..finally, parce que vous voulez garantir que Dispose () sera appelée.

Cependant, cela devient vite réel laid pour une collection. Par exemple, qu'est-ce que vous faites si l'un des appels à Dispose () levé une exception? Avez-vous l'avalez (ce qui est « mauvais ») afin que vous puissiez continuer à éliminer l'élément suivant?

Ou, proposez-vous que je viens d'appeler myDataSet.Dispose (), et oublier disposer les DataTables myDataSet.Tables?

Était-ce utile?

La solution

Voici quelques discussions expliquant pourquoi Dispose est pas nécessaire pour un DataSet.

Pour se débarrasser ou de ne pas jeter :

  

La méthode Dispose dans DataSet existe seulement à cause de l'effet secondaire de inheritance-- autrement dit, il ne fait pas réellement quelque chose d'utile dans la finalisation.

doit éliminer l'appeler sur des objets DataTable et DataSet comprend une explication d'un MVP:

  

L'espace de noms system.data (ADONET) ne contient pas   ressources non gérées. Par conséquent, il n'y a pas besoin de disposer ces objets comme   que vous ne vous êtes pas ajouté quelque chose de spécial à lui.

Comprendre la méthode Dispose et des ensembles de données? a un commentaire avec de l'autorité Scott Allen:

  

En pratique, nous disposons rarement d'un DataSet car il offre peu d'avantages "

Ainsi, le consensus, il est que il n'y a actuellement aucune bonne raison d'appeler Dispose sur un DataSet.

Autres conseils

Mise à jour (1 Décembre 2009):

Je voudrais modifier cette réponse et concède que la réponse était entachée d'erreurs.

L'analyse originale Finalité appliquer à des objets qui nécessitent la finalisation - et le point que les pratiques ne devraient pas être acceptés à la surface sans précision, une compréhension en profondeur encore des stands.

Cependant, il se trouve que DataSets, DataViews, DataTables répriment la finalisation de leurs constructeurs - c'est pourquoi appeler Dispose () sur eux ne rien explicitement

.

On peut supposer que cela se produit parce qu'ils ne disposent pas de ressources non gérés; malgré le fait que MarshalByValueComponent fait des allocations pour les ressources non gérées, ces mises en œuvre particulières n'ont pas besoin et ne peuvent donc renoncer à la finalisation.

(que les auteurs .NET prendraient soin de supprimer la finalisation des types mêmes qui occupent normalement le plus de mémoire témoigne de l'importance de cette pratique en général pour les types finalisables.)

Malgré que ces détails sont encore peu documentées depuis la création du .NET Framework (il y a près de 8 ans) est assez surprenant (que vous êtes essentiellement laissé à vos propres moyens pour passer au crible si des documents contradictoires, ambigus pour mettre les morceaux ensemble est parfois frustrant, mais ne fournit une compréhension plus complète du cadre que nous dépendons tous les jours).

Après beaucoup de lecture, voici ma compréhension:

Si un objet nécessite la finalisation, il peut occupent la mémoire plus longue que nécessaire - voici pourquoi: a) Tout type qui définit un destructor (ou hérite d'un type qui définit une destructor) est considéré comme finalisable; b) Sur l'affectation (avant que le constructeur exécute), un pointeur est placé sur la file d'attente finalisation; c) Un objet finalisable exige normalement 2 collections à récupérer (au lieu de 1) la norme; d) mise au point La suppression ne supprime pas un objet de la file d'attente de finalisation (tel que rapporté par! FinalizeQueue dans SOS) Cette commande est trompeuse; Savoir ce que les objets sont sur la file d'attente de finalisation (en soi) n'est pas utile; Savoir quels objets sont sur la file d'attente de finalisation et nécessite encore la finalisation serait utile (est-il une commande pour cela?)
finalisation un peu se supprimer hors dans l'en-tête de l'objet indiquant l'exécution qu'il n'a pas besoin d'avoir son Finalizer invoqué (n'a pas besoin de déplacer la file d'attente FReachable); Il reste sur la file d'attente Finalisation (et continue d'être rapporté par! FinalizeQueue dans SOS)

Le DataTable, DataSet, les classes DataView sont tous ancrés à MarshalByValueComponent, un objet finalisables qui peut (potentiellement) gérer les ressources non gérés

  • Parce que DataTable, DataSet, DataView ne présente pas les ressources non gérés, ils suppriment la finalisation de leurs constructeurs
  • Bien que ce soit un schéma inhabituel, il libère l'appelant d'avoir à se soucier d'appeler Jeter après usage
  • Ceci, et le fait que DataTables peuvent potentiellement être partagés entre les différents groupes de données, est probablement pourquoi DataSets ne se soucient pas de disposer DataTables enfants
  • Cela signifie également que ces objets apparaîtront sous la FinalizeQueue! SOS dans
  • Cependant, ces objets doivent encore être après une seule reclaimable collection, comme leurs homologues non-finalisables

4 (nouvelles références):

Réponse d'origine:

Il y a beaucoup de réponses trompeuses et généralement très pauvres à ce sujet -. Quelqu'un qui a débarqué ici devrait ignorer le bruit et lire les références ci-dessous attentivement

Sans aucun doute, Jeter doit être a appelé tous les objets finalisables.

DataTables sont finalisables.

L'appel Éliminez de manière significative accélère la récupération de la mémoire.

MarshalByValueComponent Appels GC.SuppressFinalize (this) dans son Dispose () - sauter cela signifie avoir à attendre des dizaines, voire des centaines de collections Gen0 avant que la mémoire est remis en état:

  

Grâce à cette compréhension de base de la finalisation, nous   peut déjà en déduire une très importante   choses:

     

Tout d'abord, les objets qui ont besoin de finalisation   vivent plus longtemps que les objets qui ne sont pas.   En fait, ils peuvent vivre beaucoup plus longtemps.   Par exemple, supposons un objet   est en Gen2 doit être finalisé.   Finalisation sera programmée mais le   l'objet est toujours en Gen2, est   ne pas être recueillies de nouveau jusqu'à la prochaine   collection gen2 arrive. Cela pourrait être   un temps très long, et, en fait,   si les choses vont bien que ce sera un   longtemps, parce que les collections de Gen2   sont coûteux et nous voulons donc qu'ils   se produire très rarement. Plus âgée   objets ayant besoin de finalisation pourrait   attendre des dizaines sinon   des centaines de collections de Gen0 avant   leur espace est récupéré.

     

En second lieu, les objets qui ont besoin de finalisation   causer des dommages collatéraux. depuis la   pointeurs d'objets internes doivent rester   valides, non seulement les objets   besoin directement Linger finalisation   en mémoire, mais tout l'objet   se réfère à, directement ou indirectement,   Ils resteront également en mémoire. Si un grand   arborescence d'objets a été ancré par un   Un seul objet que nécessaire   la finalisation, l'arbre entier   s'attarder, potentiellement pendant une longue   temps que nous venons de parler. Il est   donc important d'utiliser finalizers   avec parcimonie et placez-les sur des objets   qui ont comme objet interne peu   pointeurs que possible. Dans l'arbre   par exemple je viens de donner, vous pouvez facilement   éviter le problème en déplaçant le   ressources dans le besoin de mise au point à un   objet séparé et une tenue   référence à cet objet dans la racine   de l'arbre. Avec ce changement modeste   seul l'un objet (espérons une belle   petit objet) s'attarder et   finalisation des coûts est réduite au minimum.

     

Enfin, les objets besoin finalisation   créer du travail pour le thread finaliseur.   Si votre processus de finalisation est   un complexe, le seul et unique   thread finaliseur consacrerez   beaucoup de temps à effectuer ces étapes,   ce qui peut provoquer un arriéré de travail et   provoquent donc plus d'objets à attardent   en attente de finalisation. Donc,   il est extrêmement important que   finalizers font le moins de travail   possible. Rappelez-vous aussi que, bien que   tous les pointeurs d'objet restent valables   au cours de finalisation, il pourrait être   cas que ces pointeurs conduisent à   des objets qui ont déjà été   finalisé et pourrait donc être moins   qu'utile. Il est généralement plus sûr de   éviter de suivre les pointeurs d'objet dans   Code finalisation, même si la   pointeurs sont valides. Un coffre-fort, court   chemin de code finalisation est le meilleur.

Prenez-le de quelqu'un qui a vu 100s de MBs de DataTables non référencé dans Gen2: ceci est extrêmement important et completely 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.entry 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- cadre / Inside-the-CLR / automatique-mémoire-gestion /

Vous devez supposer qu'il fait quelque chose d'utile et appeler Dispose même si elle ne fait rien en cours. NET Framework incarnations, il n'y a aucune garantie que le restera dans les prochaines versions menant à une utilisation inefficace des ressources.

Même si l'objet n'a pas de ressources non gérés, la disposition pourrait aider GC en brisant des graphes 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 ne dépend pas de la classe donnée. En cas de DataSet, la mise en œuvre Dispose () est héritée de MarshalByValueComponent. Il se retire du récipient et appelle événement Disposed. Le code source est ci-dessous (avec réflecteur démonté .NET):

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        lock (this)
        {
            if ((this.site != null) && (this.site.Container != null))
            {
                this.site.Container.Remove(this);
            }
            if (this.events != null)
            {
                EventHandler handler = (EventHandler) this.events[EventDisposed];
                if (handler != null)
                {
                    handler(this, EventArgs.Empty);
                }
            }
        }
    }
}

Avez-vous créer des DataTables vous-même? Parce que les enfants itérer de tout objet (comme dans DataSet.Tables) est généralement pas nécessaire, car il est le travail du parent de disposer tout ce qu'il est membres de l'enfant.

En général, la règle est: Si vous avez créé et il implémente IDisposable, la jeter. Si vous ne l'avez pas créé, alors ne jetez pas, c'est le travail de l'objet parent. Mais chaque objet peut avoir des règles spéciales, consultez la documentation.

Pour .NET 3.5, il est dit explicitement « Jeter quand ne pas utiliser plus », de sorte que ce que je ferais.

J'appelle disposer à tout moment un objet implémente IDisposeable. Il est là pour une raison.

DataSets peuvent être énormes porcs de mémoire. Le plus tôt ils peuvent être marqués pour le nettoyage, le mieux.

mise à jour

Il a été 5 ans que je répondu à cette question. Je suis toujours d'accord avec ma réponse. S'il y a une méthode dispose, il doit être appelé lorsque vous avez terminé avec l'objet. L'interface a été mis en œuvre IDispose pour une raison.

Si vous avez l'intention ou le contexte de cette question est vraiment la collecte des ordures, vous pouvez définir les jeux de données et datatables null explicitement ou utiliser le mot-clé à l'aide et laissez-les hors de portée. Jeter ne fait pas grand-chose comme tétraneutron dit plus tôt. GC recueillera des objets ensemble de données qui ne sont plus référencés et aussi ceux qui sont hors de portée.

Je souhaite vraiment que les gens contribuent à abaisser le vote à écrire un commentaire fait avant downvoting la réponse.

datasets mettre en œuvre MarshalByValueComponent approfondie IDisposable, qui met en œuvre IDisposable. Étant donné que les ensembles de données sont gérées, il n'y a aucun avantage réel pour appeler disposer.

Essayez d'utiliser la fonction Clear (). Il fonctionne très bien pour moi pour l'élimination.

DataTable dt = GetDataSchema();
//populate dt, do whatever...
dt.Clear();
  

Pas besoin de disposer ()     parce que DataSet classe héritera MarshalByValueComponent et MarshalByValueComponent implémenter l'interface IDisposable

Tout d'abord je vérifier ce Éliminez le fait avec un DataSet. Peut-être en utilisant le réflecteur de Redgate vous aidera.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top