DataSet und DataTable implementieren beide IDisposable, daher sollte ich nach herkömmlichen Best Practices ihre Dispose () -Methoden aufrufen.
Nach dem, was ich bisher gelesen habe, verfügen DataSet und DataTable jedoch nicht über nicht verwaltete Ressourcen, sodass Dispose () nicht viel bewirkt.
Außerdem kann ich nicht einfach verwenden, using(DataSet myDataSet...)
da DataSet eine Sammlung von DataTables enthält.
Um sicher zu gehen, muss ich also myDataSet.Tables durchlaufen, alle DataTables entsorgen und dann das DataSet entsorgen.
Lohnt es sich also, Dispose () für alle meine DataSets und DataTables aufzurufen?
Nachtrag:
Für diejenigen unter Ihnen, die der Meinung sind, dass DataSet entsorgt werden sollte: Im Allgemeinen ist das Entsorgungsmuster die Verwendung von using
oder try..finally
, weil Sie sicherstellen möchten, dass Dispose () aufgerufen wird.
Für eine Sammlung wird dies jedoch sehr schnell hässlich. Was tun Sie beispielsweise, wenn einer der Aufrufe von Dispose () eine Ausnahme auslöst? Schlucken Sie es (was "schlecht" ist), damit Sie das nächste Element weiter entsorgen können?
Oder schlagen Sie vor, dass ich einfach myDataSet.Dispose () aufrufe und vergesse, die DataTables in myDataSet.Tables zu entsorgen?
Antworten:
Im Folgenden werden einige Diskussionen erläutert, warum Dispose für ein DataSet nicht erforderlich ist.
Entsorgen oder nicht entsorgen? ::
Sollte Dispose für DataTable- und DataSet-Objekte aufgerufen werden? enthält einige Erklärungen von einem MVP:
Grundlegendes zur Entsorgungsmethode und zu Datensätzen? hat einen mit Kommentar von Autorität Scott Allen:
Es besteht also Konsens darüber, dass es derzeit keinen guten Grund gibt, Dispose in einem DataSet aufzurufen.
quelle
using
Block aufgerufen wird, liegt bei Ihnen.Update (1. Dezember 2009):
Ich möchte diese Antwort ändern und zugeben, dass die ursprüngliche Antwort fehlerhaft war.
Die ursprüngliche Analyse gilt für Objekte, die finalisiert werden müssen - und der Punkt, an dem Praktiken ohne ein genaues, tiefgreifendes Verständnis nicht an der Oberfläche akzeptiert werden sollten, bleibt bestehen.
Es stellt sich jedoch heraus, dass DataSets, DataViews und DataTables die Finalisierung in ihren Konstruktoren unterdrücken. Aus diesem Grund führt der explizite Aufruf von Dispose () für sie nichts aus.
Vermutlich geschieht dies, weil sie nicht über nicht verwaltete Ressourcen verfügen. Trotz der Tatsache, dass MarshalByValueComponent nicht verwaltete Ressourcen berücksichtigt, sind diese speziellen Implementierungen nicht erforderlich und können daher auf die Finalisierung verzichten.
(Dass .NET-Autoren darauf achten würden, die Finalisierung für genau die Typen zu unterdrücken, die normalerweise den meisten Speicher belegen, spricht für die Bedeutung dieser Vorgehensweise im Allgemeinen für finalisierbare Typen.)
Ungeachtet dessen ist es ziemlich überraschend, dass diese Details seit der Einführung von .NET Framework (vor fast 8 Jahren) immer noch nicht ausreichend dokumentiert sind (dass Sie im Wesentlichen Ihren eigenen Geräten überlassen bleiben, um widersprüchliches, mehrdeutiges Material zu sichten, um die Teile zusammenzusetzen ist manchmal frustrierend, bietet aber ein umfassenderes Verständnis des Rahmens, auf den wir uns täglich verlassen).
Nach vielem Lesen verstehe ich Folgendes:
Wenn ein Objekt Abschluss erfordert, es könnte Speicher länger einnehmen als nötig - hier ist der Grund: a) Jede Art , die eine destructor (oder erbt von einem Typ definiert , dass ein destructor definiert) finalizable betrachtet wird; b) Bei der Zuweisung (bevor der Konstruktor ausgeführt wird) wird ein Zeiger auf die Finalisierungswarteschlange gesetzt. c) Für ein finalisierbares Objekt müssen normalerweise 2 Sammlungen zurückgefordert werden (anstelle von Standard 1). d) Durch das Unterdrücken der Finalisierung wird kein Objekt aus der Finalisierungswarteschlange entfernt (wie von! FinalizeQueue in SOS gemeldet). Dieser Befehl ist irreführend. Es ist nicht hilfreich zu wissen, welche Objekte sich in der Finalisierungswarteschlange befinden (an und für sich). Es wäre hilfreich zu wissen, welche Objekte sich in der Finalisierungswarteschlange befinden und noch finalisiert werden müssen (gibt es dafür einen Befehl?)
Das Unterdrücken der Finalisierung wird im Header des Objekts etwas deaktiviert, um der Laufzeit anzuzeigen, dass der Finalizer nicht aufgerufen werden muss (die FReachable-Warteschlange muss nicht verschoben werden). Es bleibt in der Finalisierungswarteschlange (und wird weiterhin von! FinalizeQueue in SOS gemeldet).
Die Klassen DataTable, DataSet und DataView basieren alle auf MarshalByValueComponent, einem finalisierbaren Objekt, das (möglicherweise) nicht verwaltete Ressourcen verarbeiten kann
4 (neue Referenzen):
Ursprüngliche Antwort:
Es gibt viele irreführende und im Allgemeinen sehr schlechte Antworten darauf - jeder, der hier gelandet ist, sollte den Lärm ignorieren und die folgenden Referenzen sorgfältig lesen.
Ohne Zweifel entsorgen sollte werden auf irgendwelchen Finalizable Objekte bezeichnet.
DataTables sind finalisierbar.
Calling Dispose beschleunigt die Speicherwiederherstellung erheblich .
MarshalByValueComponent ruft GC.SuppressFinalize (this) in Dispose () auf. Wenn Sie dies überspringen, müssen Sie auf Dutzende, wenn nicht Hunderte von Gen0-Sammlungen warten, bevor der Speicher wiederhergestellt wird:
Nehmen Sie es von jemandem, der in Gen2 Hunderte von MBs nicht referenzierter DataTables gesehen hat: Dies ist äußerst wichtig und wird von den Antworten in diesem Thread völlig übersehen.
Verweise:
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-framework/Inside-the-CLR/Automatic-Memory-Management/
quelle
TableAdapter
s?Sie sollten davon ausgehen, dass es etwas Nützliches tut, und Dispose aufrufen, auch wenn es im Moment nichts tut. Inkarnationen von NET Framework gibt es keine Garantie dafür, dass dies in zukünftigen Versionen so bleibt, was zu einer ineffizienten Ressourcennutzung führt.
quelle
DataTable
nicht besiegelt ist - keine große Sache, wenn Sie dies tunnew DataTable
, aber sehr wichtig, wenn Sie aDataTable
als Argument oder als Ergebnis eines Methodenaufrufs verwenden.Selbst wenn das Objekt keine nicht verwalteten Ressourcen hat, kann das Entsorgen der GC helfen, indem Objektdiagramme beschädigt werden. Wenn das Objekt IDisposable implementiert, sollte im Allgemeinen Dispose () aufgerufen werden.
Ob Dispose () tatsächlich etwas tut oder nicht, hängt von der jeweiligen Klasse ab. Im Fall von DataSet wird die Dispose () - Implementierung von MarshalByValueComponent geerbt. Es entfernt sich aus dem Container und ruft das Ereignis Disposed auf. Der Quellcode ist unten (mit .NET Reflector zerlegt):
quelle
Erstellen Sie die DataTables selbst? Da das Durchlaufen der untergeordneten Elemente eines Objekts (wie in DataSet.Tables) normalerweise nicht erforderlich ist, ist es Aufgabe des übergeordneten Elements, alle untergeordneten Mitglieder zu entsorgen.
Im Allgemeinen lautet die Regel: Wenn Sie es erstellt haben und es IDisposable implementiert, entsorgen Sie es. Wenn Sie es NICHT erstellt haben, entsorgen Sie es NICHT, das ist die Aufgabe des übergeordneten Objekts. Für jedes Objekt gelten jedoch möglicherweise spezielle Regeln. Überprüfen Sie die Dokumentation.
Für .net 3.5 heißt es explizit "Entsorgen, wenn es nicht mehr verwendet wird", also würde ich das tun.
quelle
Ich rufe dispose immer dann auf, wenn ein Objekt IDisposeable implementiert. Es ist aus einem Grund da.
DataSets können riesige Speicherfresser sein. Je früher sie zum Aufräumen markiert werden können, desto besser.
aktualisieren
Es ist 5 Jahre her, seit ich diese Frage beantwortet habe. Ich stimme meiner Antwort immer noch zu. Wenn es eine Dispose-Methode gibt, sollte diese aufgerufen werden, wenn Sie mit dem Objekt fertig sind. Die IDispose-Schnittstelle wurde aus einem bestimmten Grund implementiert.
quelle
Wenn Ihre Absicht oder der Kontext dieser Frage wirklich die Speicherbereinigung ist, können Sie die Datasets und Datentabellen explizit auf null setzen oder das Schlüsselwort using verwenden und sie außerhalb des Gültigkeitsbereichs lassen. Dispose macht nicht viel, wie Tetraneutron es früher gesagt hat. GC sammelt Datensatzobjekte, auf die nicht mehr verwiesen wird, sowie solche, die außerhalb des Gültigkeitsbereichs liegen.
Ich wünschte wirklich, SO hätte die Leute gezwungen, einen Kommentar zu schreiben, bevor sie die Antwort ablehnen.
quelle
Datensätze implementieren IDisposable gründlich MarshalByValueComponent, das IDisposable implementiert. Da Datasets verwaltet werden, hat der Aufruf von dispose keinen wirklichen Vorteil.
quelle
Versuchen Sie, die Funktion Clear () zu verwenden. Es funktioniert gut für mich zum Entsorgen.
quelle
quelle