Laden...

Probleme bei der Speicherfreigabe

Erstellt von Leon Fuxfell vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.122 Views
L
Leon Fuxfell Themenstarter:in
11 Beiträge seit 2011
vor 12 Jahren
Probleme bei der Speicherfreigabe

Ich benutze In meinem Map Editor einige streams unter anderem um Bilder zu laden oder Maps auszulesen.

Ich habe mittlerweile so ziemlich jede Methode ausprobiert den Speicher des streams wieder freizugeben.

using (myWriter)
{}

try { }
catch { }
finally { <eine der folgenden Aufrufe> }

myWriter.Close();
myWriter.Dispose();
myWriter = null;

Das Ergebnis bleibt das selbe mein Programm braucht viel zu viel Speicher. Der .Net Memory profiler meint dazu folgendes "This type has 5,764 instances that have been disposed but are still not GCed. Investigate the instances below for more information." This type ist in meinen fall natürlich "System.IO.Filestream". Nur leider verstehe ich nicht so richtig was er meint und vorallem nicht wie ich das Problem lössen kann.

Ich habe auch schon manuell den GG aufgerufen oder den Speicher mit einer weiteren Instanz meines Editors gefüllt um zusehen ob er den Speicher dann freigibt aber das ist auch nicht der Fall.

Mir ist bewusst das es sich hierbei eigentlich um einer dieser unerwünschten Anfängerfragen handeln dürfte aber ich suche nun schon mehrere Stunden im Internet und finde keine Losung. Ich hoffe ihr habt Verständnis dafür das ich aus dem Grund einfach doch eine frage für das forum daraus gemacht habe.

An dieser stelle würden wohl im Normalfall einige Codezeilen stehen. Da ich aber nicht weiß wo und warum das Problem auftritt weiß ich nicht so recht welche Codeausschnitte für mein Problem nötig sind.

MFG Leon

16.842 Beiträge seit 2008
vor 12 Jahren

... zur Zeit häufen sich irgendwie die Fragen bezüglich Speicherfreigabe 🤔

Benutze am Besten die Using-Variante; ansonsten musst Du Dich "um nichts" kümmern.
Der GC räumt dann auf, wenn er es für richtig hält und es gerade passt bzw nötig ist.

Die beiden Beiträge von herbivore und mir in wechselnder Speicherverbrauch, ohne dass es nötig wäre treffen das ganze auf den Punkt - auch in diesem Fall.

Dass Du über 5000 Streams haben sollst, wenn Du aber nur einen öffnest, ist ungewöhnlich.
Jedenfalls passt Deine Beschreibung nicht zu dieser Meldung; duplizierst Du vielleicht den Stream? Zeig mal, was innerhalb des Usings steht.

L
Leon Fuxfell Themenstarter:in
11 Beiträge seit 2011
vor 12 Jahren

Ich habe auch schon manuell den GG aufgerufen oder den Speicher mit einer weiteren Instanz meines Editors gefüllt um zusehen ob er den Speicher dann freigibt aber das ist auch nicht der Fall.

Mein problem ist das der speicher definitiv nicht freigegeben wird. Ein andere instanz geht ehr mit einem "System.OutOfMemoryException" zu grunde als den speicher zu bekommen.

Und System.GC.Collect(); zeigt auch keine wirkung.

Sorry das mit den vielen instansen.


private void LoadImage() // Diese methode wird von dem Konstruktor von Tile aufgerufen
{
  using (FileStream stream = new FileStream(MainPath + "\\tile\\" + Path, FileMode.Open))
  {
    image = Image.FromStream(stream);
  }
}


List<Tile> TileData = new List<Tile>();

public void AddTile(string TilePath)
{
  TileList.Add(TilePath);
  TileData.Add(new Tile(TilePath, MainPath));
}

Ja ich sehe auch ein das das evt nicht die beste Lösung ist aber trotzdem sollte ich meinen Speicher doch wieder bekommen. Oder?

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Leon Fuxfell,

woher weiß du, dass die Streams das Problem sind und nicht z.B. die Bilder?

Zwar wird durch myWriter = null; nicht der Speicher des Objekts freigegeben, aber wenn es die letzte Referenz war, wird zumindest sichergestellt, dass der GC den Speicher freigeben kann, wenn er anderweitig benötigt wird. Insofern sollte es wegen des verwalteten Speichers zu einer OutOfMemoryException nicht kommen.

Allerdings kommt eine OutOfMemoryException nicht nur bei verwaltetem Speicher. Es kann sich um jede Art von Speicher handeln, der erschöpft ist, also z.B. wenn Tabellen im Betriebssystem voll laufen. Window Handles sind z.B. ein eher knappes Gut. Wenn also eine OutOfMemoryException kommt, würde ich eher auf nicht-verwaltete Ressourcen tippen und damit auf vergessene Dispose (wieder nicht unbedingt bei den Streams).

herbivore

PS: Dein erste Codebeispiel ist schon mal Mist. Es ist nicht erlaubt, den Strom zu schließen, solange das Bild noch lebt.

Sinnvoll wäre, wenn du pro TilePath nur einmal ein Image-Objekt erstellst.

L
Leon Fuxfell Themenstarter:in
11 Beiträge seit 2011
vor 12 Jahren

Danke euch beiden für eure Antworten. Ich werde den stream also im Speicher lassen müssen.

Das ergibt für mein Programm leider ein neues Problem. Ich benötige einen Stream von der selben Datei um ein System.Drawing.Image und eine XNA 2d Textur zu erzeugen.

Wen ich den Stream nicht schließen darf kann ich aber auch keinen neuen erzeugen.

Habe ich etwas übersehen oder muss ich mir den Orginalstream aus Tile besorgen?

Gruß Leon

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Leon Fuxfell,

ob du einen Strom mehrfach öffnen kannst, hängt von File.Share-Modus ab. Ansonsten ist das Problem mit den offenen Strom bei Bildern altbekannt, und das brauchen wir daher auch nicht immer wieder neu zu besprechen, siehe Dateizugriff durch Bitmap-Objekt beenden.

herbivore

L
Leon Fuxfell Themenstarter:in
11 Beiträge seit 2011
vor 12 Jahren

...und das brauchen wir daher auch nicht immer wieder neu zu besprechen...

Natürlich nicht Entschuldingung das ich hier nicht richtig gesucht habe. Und danke für den Link.

Ich habe für mein Programm ohne Tile etwa 30 MB im Speicher. Es gibt ca 5000 Tiles die geladen werden. Auf der Platte sind das im Gesamten ca 2,5 MB. Und sie werden zwei mal geladen.

Mit Streams komme ich auf ca 370 MB im Speicher.

Das kommt mir etwas viel vor. Gibt es denn keine möglichkeit den Stream von dem Imgae abzutrennen? (Oder auf anderem Weg Bilder ohne Stream zu verarbeiten)

Gruß Leon

156 Beiträge seit 2010
vor 12 Jahren

Es gibt ca 5000 Tiles die geladen werden. Auf der Platte sind das im Gesamten ca 2,5 MB. Und sie werden zwei mal geladen. Das kommt mir etwas viel vor.

sind die Tiles komprimiert oder als RAW-Datei auf der Festplatte? ... und wieso werden die Tiles 2 mal geladen - reicht einmal nicht aus?

Gibt es denn keine möglichkeit den Stream von dem Imgae abzutrennen? (Oder auf anderem Weg Bilder ohne Stream zu verarbeiten)

ja - in dem Du das Bild auf Bild zeichnest und das Bild zerstörst (entwirren darfst Du) ... dann kannst Du den Stream zerstören ... alternativ kannst Du die Bild daten auch in einen MemoryStream stecken und von da das Bild erzeugen

hand, mogel