2010-01-07 8 views
6

Ich habe mit anderen Methoden experimentiert, um einige Speicherlecks in meiner Anwendung loszuwerden, als ich realisierte, dass ich praktisch nichts über die Bereinigung meiner Ressourcen weiß. Ich recherchierte und hoffte, dass das Aufrufen der .dispose() alle meine Probleme lösen würde. Wir haben eine Tabelle in unserer Datenbank, die etwa 65.000 Datensätze enthält. Offensichtlich kann die Speicherauslastung ziemlich hoch werden, wenn ich meine Datenmenge vom Datenadapter aus fülle. Als ich die Dispose-Methode für das Dataset anrief, war ich überrascht herauszufinden, dass KEIN der Speicher freigegeben wurde. Warum ist das passiert? Das Löschen des Datensatzes hilft auch nicht.Führt die .dispose() -Methode überhaupt etwas aus?

Antwort

25

IDisposable und somit Dispose wird nicht verwendet, um den Arbeitsspeicherdruck zu reduzieren, obwohl es in einigen Fällen vielleicht, aber stattdessen für deterministische Bereinigung verwendet wird.

Betrachten Sie dies, konstruieren Sie ein Objekt, das eine aktive und offene Verbindung zu Ihrem Datenbankserver unterhält. Diese Verbindung verwendet Ressourcen sowohl auf Ihrem Computer als auch auf dem Server.

Sie könnten natürlich das Objekt einfach lassen, wenn Sie damit fertig sind, und schließlich wird es vom Müllsammler aufgenommen, aber angenommen, Sie wollen sicherstellen, dass zumindest die Ressourcen freigegeben werden und somit Die Verbindung ist geschlossen, wenn du damit fertig bist. Dies ist wo IDisposable. Dispose kommt ins Spiel.

Es wird verwendet, um Ressourcen zu bereinigen, die vom Objekt verwaltet werden.

Es wird jedoch nicht den verwalteten Speicher freigeben, der dem Objekt zugewiesen ist. Dies wird immer noch dem Garbage Collector überlassen, der zu einem späteren Zeitpunkt dazu kommen wird.

Haben Sie tatsächlich ein Speicherproblem, oder betrachten Sie nur die Speicherauslastung im Task-Manager oder ähnlichem und gehen Sie "das ist ein bisschen hoch."?

Wenn letzteres, dann sollten Sie es für jetzt sein lassen. .NET führt die Garbage Collection häufiger aus, wenn weniger Arbeitsspeicher zur Verfügung steht. Wenn Sie sich also nicht in einer Situation befinden, in der Sie möglicherweise eine Speicherüberlaufbedingung erhalten oder vermuten, dass dies bald der Fall sein wird, werden Sie wahrscheinlich keine Probleme haben .

Lassen Sie mich erklären, was ich unter "weniger oft laufen" verstehe.

Wenn auf Ihrem Computer 8 GB Arbeitsspeicher vorhanden sind und nur Windows und Notepad ausgeführt werden, ist der größte Teil des Arbeitsspeichers verfügbar. Wenn Sie jetzt Ihr Programm ausführen, auch wenn es kleinere Datenblöcke in den Arbeitsspeicher lädt, können Sie dies für eine lange Zeit tun, und die Speichernutzung wird stetig zunehmen. Wann genau der GC einsteigen und versuchen wird, Ihren Speicherbedarf zu reduzieren, weiß ich nicht, aber ich kann Ihnen fast garantieren, dass Sie sich fragen werden, warum er so hoch wird.

Lassen Sie uns nur für das Argument sagen, dass Ihr Programm schließlich 2 GB Speicher verwenden wird.

Wenn Sie Ihr Programm jetzt auf einem Computer ausführen, auf dem weniger Arbeitsspeicher verfügbar ist, wird GC häufiger auftreten und auf einen unteren Grenzwert zugreifen, wodurch der Arbeitsspeicher möglicherweise unter 500 MB oder sogar noch weniger bleibt.

Der wichtige Teil hier zu beachten ist, dass, damit Sie ein genaues Bild davon erhalten, wie viel Speicheranwendung tatsächlich erfordert, dann können Sie nicht auf Task-Manager oder ähnliche Möglichkeiten zu messen, benötigen Sie etwas zielgerichteter.

+0

Mein Programm kann bis zu 700,164k erreichen. Nicht gut, wenn man bedenkt, dass meine Kunden weniger Computer haben. – broke

+6

was bedeutet, dass du meine Antwort nicht gelesen hast. Versuchen Sie, mehrere große Anwendungen zu laden, sodass Sie vor dem Start Ihres eigenen Programms weniger als 700.164 KByte Speicher (einschließlich virtuellem Speicher) zur Verfügung haben. Dann versuchen Sie es zu laden, es wird wahrscheinlich immer noch funktionieren, es sei denn, Sie laden mehr als die Daten in den Speicher für die Verwendung, in diesem Fall wird GC überhaupt nicht helfen, Sie müssen nur die Menge der Daten, die Sie verarbeiten, reduzieren jederzeit. –

+0

Okay, versuch es mal. – broke

4

Mit dem Aufruf von Dispose() werden nur nicht verwaltete Ressourcen wie Dateizugriffsnummern, Datenbankverbindungen, nicht verwalteter Speicher usw. freigegeben. Es wird nicht freigeben Speicher Garbage Collection.

Müll gesammelt Speicher wird nur bei der nächsten Sammlung freigegeben werden. Normalerweise, wenn der Speicher der Anwendungsdomäne voll ist.

3

Ich werde hier etwas hervorheben, das nicht explizit erwähnt wurde: calling Dispose() wird nur (freie) nicht verwaltete Ressourcen bereinigen, wenn der Entwickler der Komponente es codiert hat.

Was ich meine, ist: Wenn Sie vermuten, dass Sie ein Speicherleck haben, rufen Dispose() nicht beheben werde es , wenn der ursprüngliche Entwickler hat einen miesen Job gemacht und nicht korrekt nicht verwalteten Ressourcen frei. Für ein bisschen mehr Info, check this blog post. Notieren Sie sich die Anweisung Das Verhalten von Dispose wird vom Entwickler definiert.

1

Einige Objekte werden eine oder mehrere andere Entitäten auffordern, bis auf weiteres in ihrem Namen etwas zu tun, was zu Lasten anderer Entitäten geht. Wenn ein Objekt verschwinden würde, ohne die ehemaligen Entitäten darüber zu informieren, dass ihre Dienste nicht länger benötigt werden, würden diese Entitäten weiterhin nutzlos für ein Objekt handeln, das sie nicht länger benötigt, was anderen Unternehmen, die dies wünschen würden, weiter schaden würde um sie zu benutzen.

In vielen Fällen musste George für ein Objekt "George", das einer externen Entität "Joe" sagte, dass seine Dienste nicht länger benötigt wurden, seine Dienste nicht mehr benötigen. Es gibt zwei normale Möglichkeiten, über die das in .NET, Finalisierung und IDIsposable passieren kann.

Wenn ein Objekt eine Methode mit dem Namen Finalize überschreibt, wird der .NET-Garbage Collector beim Erstellen des Objekts eine Liste mit Objekten mit registrierten Finalizern hinzufügen. Wenn der GC erkennt, dass kein verwurzelter Verweis auf das Objekt außer dieser Liste vorhanden ist, entfernt der GC das Objekt aus dieser Liste und fügt es zu einer stark verwurzelten Warteschlange von Objekten hinzu, deren Methode Finalize so bald wie möglich aufgerufen werden soll. Ein solches Objekt kann dann seine Finalize-Methode verwenden, um andere Entitäten darüber zu informieren, dass ihre Dienste nicht mehr benötigt werden.

Obwohl Finalisierung-basierte Bereinigung manchmal funktionieren kann, gibt es keine Garantie für die Aktualität. An einem Punkt während des Entwurfs von .net hat Microsoft möglicherweise beabsichtigt, dass Finalisierung die primäre Bereinigungsmethode sein würde, aber aus einer Vielzahl von Gründen kann nicht sicher darauf verlassen werden.

Der andere Cleanup-Ansatz, der im Mittelpunkt der Bemühungen stehen sollte, ist IDisposable. Grundsätzlich ist die Idee hinter IDisposable einfach: Für jedes Objekt, das IDisposable implementiert, sollte es eine Entität (im Allgemeinen entweder ein Objekt oder einen verschachtelten Ausführungsbereich) geben, die dafür verantwortlich ist, dass die Methode IDisposable.Dispose irgendwann innerhalb der Lebensdauer von aufgerufen wird das Universum (was bedeuten würde, dass irgendwann ein Verweis auf das Objekt existiert) und vorzugsweise sobald der Code erkennen kann, dass die Dienste des Objekts nicht länger benötigt werden. Beachten Sie, dass IDisposable.Dispose im Allgemeinen verspricht, dass alle externen Entitäten, die gebeten wurden, etwas im Namen eines Objekts zu tun, dass sie dies nicht länger tun müssen, aber ein solches Versprechen bedeutet nicht, dass die Anzahl der Entitäten nicht ist -Null. Wenn ein Objekt keine externen Entitäten aufgefordert hat, in seinem Namen etwas zu tun, dann erfordert das Liefern einer Nachricht "alle" solchen Entitäten überhaupt nichts zu tun.Auf der anderen Seite bedeutet die Tatsache, dass eine Dispose Methode in einigen Fällen nichts tun kann, nicht, dass es garantiert ist, auf keinen Fall irgendetwas zu tun, oder dass es in Fällen, in denen es etwas tun würde, nicht fehlschlägt Schädliche Auswirkungen.

Verwandte Themen