Der folgende Code ist ein vereinfachtes Beispiel für ein Problem, das ich sehe. Diese Anwendung verbraucht ca. 4 GB Speicherplatz, bevor eine Ausnahme ausgelöst wird, da das Wörterbuch zu groß ist.
%Vor%Das ist alles wie erwartet, obwohl das, was wir derzeit nicht ausarbeiten können, ist, wenn dieser Speicher von der CLR freigegeben werden soll.
Wir haben die Aufgabe abgeschlossen und dann eine Speicherüberlastungssituation simuliert, aber der vom Wörterbuch belegte Speicher wird nicht freigegeben. Wenn das Betriebssystem nicht mehr genügend Arbeitsspeicher hat, übt es keinen Druck auf die CLR aus, um den Speicher freizugeben?
Jedoch und noch verwirrender, wenn wir warten, bis die Aufgabe abgeschlossen ist, dann Enter drücken, um die Aufgabe erneut auszuführen, wird der Speicher freigegeben, so dass offensichtlich das vorherige Wörterbuch Müll gesammelt wurde (nicht wahr?).
Also, warum wird die Erinnerung nicht freigegeben? Und wie können wir die CLR dazu bringen, die Erinnerung freizugeben?
Alle Erklärungen oder Lösungen würden sehr geschätzt werden.
EDIT: Nach den Antworten, insbesondere Beskas, ist es offensichtlich, dass meine Beschreibung des Problems nicht die klarste ist, also werde ich versuchen, dies zu klären.
Der Code ist vielleicht nicht das beste Beispiel, sorry! Es war ein schneller, primitiver Code, um das Problem zu replizieren.
Das Wörterbuch wird hier verwendet, um die Tatsache zu replizieren, dass wir ein großes benutzerdefiniertes Datenobjekt haben, das einen großen Teil unseres Speichers füllt und nicht freigegeben wird, nachdem die Aufgabe abgeschlossen ist.
Im Beispiel füllt sich das Wörterbuch bis zum Limit des Wörterbuchs und löst dann eine Ausnahme aus, es füllt sich NICHT für immer! Dies ist lange bevor unser Speicher voll ist und es keine OutOfMemoryException verursacht. Daher ist das Ergebnis ein großes Objekt im Speicher, und dann ist die Aufgabe abgeschlossen.
An diesem Punkt würden wir erwarten, dass das Wörterbuch außerhalb des Geltungsbereichs liegt, da sowohl die Aufgabe als auch die Methode "Methode" abgeschlossen sind. Daher würden wir erwarten, dass das Wörterbuch Müll gesammelt und der Speicher zurückgewonnen wird. In Wirklichkeit wird der Speicher nicht freigegeben, bis 'Methode' erneut aufgerufen wird, eine neue WasteOfMemory-Instanz erstellt und eine neue Task gestartet wird.
Hoffentlich wird das das Problem ein wenig klären
Okay, ich habe das verfolgt ... Ich denke, es gibt ein paar Probleme, von denen einige Leute berührt haben, aber ich glaube nicht, die richtige Frage zu beantworten (was zugegebenermaßen eine Weile dauerte, bis ich erkannte, und ich bin mir nicht sicher, ob ich dir jetzt antworte, was du willst.)
Das ist alles wie erwartet, obwohl das, was wir derzeit nicht ausarbeiten können, ist, wenn dieser Speicher von der CLR freigegeben werden soll.
Wie bereits erwähnt, wird das Wörterbuch während der Ausführung der Aufgabe nicht freigegeben. Es wird benutzt. Es wird größer, bis Sie keinen Speicher mehr haben. Ich bin mir ziemlich sicher, dass du das verstehst.
Wir haben die Aufgabe abgeschlossen und dann eine Speicherüberlastungssituation simuliert, aber der vom Wörterbuch belegte Speicher wird nicht freigegeben. Wenn das Betriebssystem nicht mehr genügend Arbeitsspeicher hat, übt es keinen Druck auf die CLR aus, um den Speicher freizugeben?
Hier, denke ich, ist die wirkliche Frage.
Wenn ich Sie richtig verstehe, sagen Sie, dass Sie das einrichten, um Speicher zu füllen. Und dann, nachdem es abstürzt (aber bevor du zurückkommst, um eine neue Aufgabe zu starten), versuchst du andere Dinge außerhalb dieses Programms, wie zum Beispiel das Ausführen anderer Programme in Windows , um den GC zu bekommen sammle die Erinnerung, richtig? In der Hoffnung, dass das Betriebssystem mit dem GC sprechen würde, und beginnen, Druck darauf auszuüben, es zu tun.
Jedoch und noch verwirrender, wenn wir warten, bis die Aufgabe abgeschlossen ist, dann Enter drücken, um die Aufgabe erneut auszuführen, wird der Speicher freigegeben, so dass offensichtlich das vorherige Wörterbuch Müll gesammelt wurde (nicht wahr?).
Ich denke, Sie haben Ihre eigene Frage beantwortet ... Sie wurde nicht unbedingt veröffentlicht, bis Sie auf "Zurück" klicken, um eine neue Aufgabe zu starten. Die neue Aufgabe benötigt Speicher, also geht sie zum GC, und der GC sammelt glücklicherweise den Speicher von der vorherigen Aufgabe, die nun beendet ist (nach dem Auswerfen aus dem vollen Speicher).
Also, warum wird die Erinnerung nicht freigegeben? Und wie können wir die CLR dazu bringen, die Erinnerung freizugeben?
Ich weiß nicht, dass Sie den GC zwingen können, Speicher freizugeben. Im Allgemeinen macht es es, wenn es will (obwohl einige Hacker-Typen vielleicht einen glatten Weg kennen, um ihre Hand zu erzwingen). Natürlich entscheidet .NET, wann der GC ausgeführt wird, und da nichts passiert, während das Programm gerade dort sitzt, Es kann durchaus sein, dass es nicht nötig ist. Ob das Betriebssystem den GC unter Druck setzen kann, scheint aus Ihren Tests die Antwort "nein" zu sein. Ein bisschen kontraintuitiv vielleicht.
Hast du das versucht?
Der Garbage Collector gibt nur Speicher im Speicher frei, die nicht mehr verwendet werden, also Objekte, auf die kein Zeiger zeigt.
(1) Ihr Programm läuft unendlich ohne Terminierung und
(2) Sie ändern nie den Zeiger auf Ihr Wörterbuch, sodass der GC sicherlich keinen Grund hat, das Wörterbuch zu berühren.
Ihr Programm macht also genau was es tun soll.
Der Speicher wird nicht freigegeben, da der Bereich aMassiveList
niemals beendet wird. Wenn eine Funktion zurückkehrt, gibt sie alle nicht referenzierten Ressourcen frei, die darin erstellt wurden.
In deinem Fall verlässt aMassiveList
niemals den Kontext. Wenn Sie möchten, dass Ihre Funktion niemals zurückkehrt, müssen Sie einen Weg finden, Ihre Informationen zu "verarbeiten" und sie zu veröffentlichen, anstatt sie für immer zu speichern.
Wenn Sie eine Funktion erstellen, die zunehmend Ressourcen zuweist und sie niemals freigibt, verbrauchen Sie den gesamten Speicher.
Wie Sie die WasteMemory-Methode geschrieben haben, wird sie nie beendet (es sei denn, die Variable "i" läuft über, was in diesem Jahr nicht passieren wird) und WEIL SIE NIEMALS BEENDEN IN USE der Verweis auf das interne Wörterbuch.
Daniel White hat Recht, Sie sollten darüber lesen, wie GC funktioniert.
Wenn die Referenzen verwendet werden, erfasst GC den referenzierten Speicher nicht. Wie würde sonst ein Programm funktionieren?
Ich sehe nicht, was Sie von der CLR / GC erwarten. In einem Durchlauf Ihrer WasteMemory-Methode gibt es nichts zu sammeln.
Jedoch und noch verwirrender, wenn wir warten, bis die Aufgabe abgeschlossen ist, dann Enter drücken, um die Aufgabe erneut auszuführen, wird der Speicher freigegeben, so dass offensichtlich das vorherige Wörterbuch Müll gesammelt wurde (nicht wahr?).
Wenn Sie die Eingabetaste drücken, wird eine neue Aufgabe erstellt und gestartet. Es ist nicht dieselbe Aufgabe , es ist eine neue Aufgabe - ein neues Objekt, das einen Verweis auf eine neue WasteOfMemory-Instanz enthält.
Die alte Aufgabe wird weiter ausgeführt und der verwendete Speicher wird NICHT gesammelt, da die alte Aufgabe weiterhin im Hintergrund ausgeführt wird und VERWENDET diesen Speicher verwendet.
>Ich bin nicht sicher, warum - und vor allem WIE - Sie beobachten die Erinnerung an die alte Aufgabe freigegeben werden.
Tags und Links .net c# garbage-collection memory-management