Ich habe einen Datenladeprozess, der eine große Menge an Daten in DataTable lädt und dann einige Daten verarbeitet, aber jedes Mal, wenn der Job beendet ist, gibt die DataLoader.exe (32bit, hat ein 1,5G Speicherlimit) nicht alle frei Speicher wird verwendet.
Ich habe versucht, 3 Möglichkeiten zur Freigabe von Speicher:
Nachstehend ist der Code, den ich zum Testen ausprobiert habe (im realen Programm wird er nicht rekursiv aufgerufen, er wird von einer Logik zur Verzeichnisüberwachung ausgelöst. Dieser Code dient nur zum Testen. Sorry für die Verwirrung.):
%Vor%Wenn Sie den Teil verschieben, wenn Sie ihn außerhalb der Funktion wiederholen möchten, wird der Speicher korrekt freigegeben (nur Testmethode 1 (Löschen und Entsorgen)):
%Vor%Wahrscheinlich wird der Speicher der Objekte freigegeben, wenn sie den Gültigkeitsbereich verlassen haben
Ihr Hauptproblem ist das Verhalten des Garbage Collectors, je nachdem, ob Sie debuggen oder im Release-Modus sind, ohne dass ein Debugger vorhanden ist.
Wenn ein Debug-Build oder ein Release-Build mit einem Debugger vorhanden ist, wird die Lebensdauer aller Objekte auf die gesamte Lebensdauer der Methode erweitert. Was das bedeutet, ist table
kann nicht vom GC zurückgefordert werden, bis Sie die Methode LoadData
abgeschlossen haben. Dies ist der Grund dafür, dass Ihnen immer weniger Speicher zur Verfügung steht.
Wenn Sie Ihr Programm in den Freigabemodus ändern und es ohne den Debugger ausführen, wird das Objekt, sobald Sie den letzten Verweis auf das Objekt, auf das die Variable table
verweist, in Ihrem Codepfad für Garbage Collection und Sie verfügbar machen den Speicher freimachen.
Der Grund, warum der GC sein Verhalten während einer "debuggable situation" ändert, ist der Debugger selbst, der einen Verweis auf alle Variablen enthält, die sich im Bereich des gerade ausgeführten Codes befinden. Andernfalls könnten Sie den Wert einer Variablen im Überwachungsfenster nicht ansehen oder darüber mogeln. Aus diesem Grund können Sie nicht "die letzte Referenz auf das Objekt übergeben", bis die Variable den Gültigkeitsbereich verlässt oder Sie die Variable überschreiben.
Lesen Sie den Blog-Beitrag über Garbage Collection, Scope und Object Lifetimes für detailliertere Informationen über den Prozess.
Es gibt nicht wirklich eine Möglichkeit, C # zu zwingen, Speicher freizugeben, wie dies bei Code ohne Speicherverwaltung der Fall wäre. Es hilft zu verstehen, wie der .NET-Garbage Collector funktioniert. Die Speicherauslastung in .NET-Anwendungen steigt im Grunde auf eine von drei Bedingungen, die eine Speicherbereinigung auslösen. Ich beschreibe den Prozess in der Antwort auf die folgende Frage:
Variablen in Methoden bereinigen
Eine Möglichkeit, die Ausnahme OutOfMemory
zu vermeiden, ist die Verwendung der Klasse MemoryFailPoint
, mit der Sie einen Fehlerpunkt festlegen können, ab dem ein InsufficientMemoryException
ausgelöst wird, wodurch Sie den Prozess bis zu einem anderen Worker verlangsamen können Thread ist verfügbar. Ich bin mir nicht sicher, ob dies etwas ist, was Sie ausprobieren möchten, aber es steht Ihnen zur Verfügung:
Tags und Links memory c# memory-management datatable