kostenloser Webspace werbefrei: lima-city


[C#] OutOfMemoryException bei Bildbetrachter

lima-cityForumProgrammiersprachenProgrammieren mit .NET & Mono

  1. Autor dieses Themas

    biberiusmero

    Kostenloser Webspace von biberiusmero

    biberiusmero hat kostenlosen Webspace.

    Hallo zusammen,

    ich habe in C# einen Bildbetrachter geschrieben. Die Dateinamen werden mit folgender Methode ausgelesen:
    public void Load_Pictures()
            {
                DialogResult result = folderBrowserDialog1.ShowDialog();
                if (result == DialogResult.OK)
                {
                    pictureBox1.Image = null;
                    i = 0;
                    try
                    {
                        pictures = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.jpg", SearchOption.AllDirectories);
                        Array.Sort(pictures, StringComparer.InvariantCulture);
                        pictureBox1.Image = Image.FromFile(pictures[0]);
                    }
                    catch (Exception error1)
                    {
                        pictures = null;
                        MessageBox.Show(Convert.ToString(error1));
                    }
                }
            }


    Mit den folgenden Methoden kann man das vorherige bzw. nächste Bild anzeigen lassen:
    public void Previous_Picture(object sender, EventArgs e)
            {
                try
                {
                    pictureBox1.Image = Image.FromFile(pictures[--i]);
                }
                catch(Exception)
                {
                    i++;
                }
            }
    
            public void Next_Picture(object sender, EventArgs e)
            {
                try
                {
                    pictureBox1.Image = Image.FromFile(pictures[++i]);
                }
                catch(Exception)
                {
                    i--;
                }
            }


    Das funktioniert alles soweit. Nun kommt es aber vor, wenn ich einige Bilder ansehe, dass sich mein Arbeitsspeicher immer weiter füllt, bis eine OutOfMemoryException auftritt, woraufhin man nicht mehr "weiterklicken" kann.

    Wie kann ich dieses Problem vermeiden?

    Ich hoffe auf eure Antworten

    biberiusmero

    Beitrag zuletzt geändert: 7.2.2015 21:21:43 von biberiusmero
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Ich hab zwar noch nie in C# programmiert. Aber vielleicht kann ich ja trotzdem helfen.
    Die OutOfMemoryException wird wohl in einer dieser beiden Zeilen geworfen:
    pictureBox1.Image = Image.FromFile(pictures[--i]);
    pictureBox1.Image = Image.FromFile(pictures[++i]);
    Je nachdem, ob du das vorherige Bild oder das nächste Bild möchtest.
    Dazu hab ich das gefunden:
    MSDN schreibt:
    OutOfMemoryException:
    Die Datei besitzt kein gültiges Bildformat.
    - oder -
    GDI+ unterstützt das Pixelformat der Datei nicht.
    Es gibt also offensichtlich noch mehr mögliche Gründe für diesen Fehler. Das Programm sollte dann immer beim gleichen Bild abbrechen. Entferne einmal das evtl. beschädigte Bild aus dem Verzeichnis und versuche es noch einmal.

    biberiusmero schrieb:
    Nun kommt es aber vor, wenn ich einige Bilder ansehe, dass sich mein Arbeitsspeicher immer weiter füllt, ...
    Es gibt ja noch die Garbage Collection, die für's Aufräumen zuständig ist. Wahrscheinlich ist es überhaupt kein Problem, wie sich der Speicher füllt und die Exception wird wie gesagt aus anderen Gründen geworfen.
    Sollte doch der Speicher knapp werden, müssen alte Bilder eigentlich aufgeräumt werden.
    Oder muss man Bilder explizit freigeben? Das würde mich in C# jedoch schon verwundern.
  4. Autor dieses Themas

    biberiusmero

    Kostenloser Webspace von biberiusmero

    biberiusmero hat kostenlosen Webspace.

    Hallo fuerderer,

    vielen Dank für deine schnelle Antwort. Ich denke, dass es schon an mangelndem Arbeitsspeicher liegt.
    Die Exception tritt nämlich immer auf, wenn ich einige große (~ 5 MB/Bild) Fotos anschaue. Außerdem wird mir als zusätzliche Info für die Ecxeption "Nicht genügend Arbeitsspeicher" genannt.
    Vielleicht muss man ja die Bilder wirklich freigeben, wie du gesagt hast.
    Die Fehlermeldung von Visual Studio ist übrigens:

    Eine Ausnahme (erste Chance) des Typs "System.OutOfMemoryException" ist in System.Drawing.dll aufgetreten.

    biberiusmero
  5. spackenheimer

    Kostenloser Webspace von spackenheimer

    spackenheimer hat kostenlosen Webspace.

    Was meinst du genau mit " (~ 5 MB/Bild) " ?
    Wenn die Datei z.B. im .JPG Format gespeichert ist und ein paar tausend Pixel in jede Richtung enthält,
    ist der Bedarf an RAM schon ganz enorm.
    Rechenbeispiel:
    Rohes Bild aus einer Canon EOS 5D Mark II in höchster Auflösung (5.616 x 3.744)
    braucht mindestens 5.616 x 3.744 x 3 Bytes RAM
    das wären 63078912 Bytes oder ca. 61.6 MB

    Wenn du da ein Memory Leak hast ist ziemlich schnell der Ofen aus.
    Ich würde mal im Task Manger beobachten wie der RAM Bedarf deines Programms wächst.
    Wenn's als 32-Bit Task läuft, sollte die Schmerzgrenze bei genau 2GB liegen.
  6. Autor dieses Themas

    biberiusmero

    Kostenloser Webspace von biberiusmero

    biberiusmero hat kostenlosen Webspace.

    Hallo spackenheimer,

    Mit (~ 5 MB/Bild) meine ich, dass jedes einzelne Foto ungefähr 5 MB groß ist.
    (Wenn's dich interessiert, die Fotos kommen hauptsächlich von einer Sony Alpha 58, Auflösung 5456 x 3632).
    Ja, das Programm läuft als 32-Bit Task, Schluss ist bei knapp über 1 GB "RAM-Verbrauch".

    Mir ist klar, dass der RAM recht schnell voll wird, wenn viele große Fotos geladen werden, aber ich will ja eigentlich nicht, dass alle Fotos im RAM bleiben, theoretisch würde es ja reichen, wenn das aktuelle im Arbeitsspeicher ist (bzw. noch 2 - 3 Fotos "vorgeladen" werden würden und die letzten 2 - 3 Fotos noch im Arbeitsspeicher verbleiben).

    Gibt es eine Möglichkeit das irgendwie mit C# zu realisieren, also evtl. mit einer Methode, die die Bilder wieder aus dem RAM löscht?

    MfG
    biberiusmero
  7. biberiusmero schrieb:
    Gibt es eine Möglichkeit das irgendwie mit C# zu realisieren, also evtl. mit einer Methode, die die Bilder wieder aus dem RAM löscht?
    Das geht vielleicht über die Methode Dispose() auf dem Image Objekt.
    Laut MSDN:
    Dispose() Gibt alle von diesem Image verwendeten Ressourcen frei.
    Wenn nicht, dann schau mal noch die anderen Methoden durch. Vielleicht ist was dabei.
  8. Autor dieses Themas

    biberiusmero

    Kostenloser Webspace von biberiusmero

    biberiusmero hat kostenlosen Webspace.

    Hallo fuerderer,

    vielen Dank für deine Antwort. Mit der Dispose() Methode hat's funktioniert. Jetzt bleibt die RAM-Nutzung in etwa konstant. (Auf jeden Fall steigt sie nicht mit jedem Bild an, bis es kracht...)

    Ich habe jetzt einfach geschrieben:
    pictureBox1.Image.Dispose();
    pictureBox1.Image = Image.FromFile(pictures[++i]);


    Und so läuft's. Vielen Dank noch mal an alle, die sich die Mühe gemacht haben, mir zu helfen.

    biberiusmero
  9. Moinsen,

    ich hab deine Application mal eben schnell "nachgebaut" und getestet.

    Bei mir ist die OutOfMemoryException nicht aufgetreten.
    Hab beim Testing ein Ordner mit 1GB Bilder alle ca. 4~5 MB groß genutzt.

    Fraglich, was ist bei dir noch so alles im Programm ist, dass du überhaupt das Dispose selber anstoßen musst?
    Nochmalweise macht das der GC selber, wenn er die notwendigkeit dazu sieht.
    Hat er bei mir immer bei ca. 1GB Arbeitsspeicher gemacht.

    MfG Trancer

    Edit:
    Außerdem möchte ich noch anmerken, dass das Setzen des Label-Text bei Durchblättern auch sinn macht und nicht nur einmal, wenn man den Ordner auswählt.

    Zudem warum eigentlich nicht wieder beim ersten Bild anfangen, wenn man beim Letzten angekommen ist und noch einmal auf next klickt bzw. andersrum ?

    Beitrag zuletzt geändert: 7.2.2015 21:09:18 von trancedrome
  10. Autor dieses Themas

    biberiusmero

    Kostenloser Webspace von biberiusmero

    biberiusmero hat kostenlosen Webspace.

    Hallo trancedrome,

    das mit der OutOfMemoryException kann ich mir eigentlich nur so erklären, dass beim Drücken auf den Next-Button immer wieder das Bild aus der Datei in den RAM geladen und dann in der pictureBox angezeigt wurde. Ich weiß nicht, wieso es dann nicht automatisch wieder entfernt wurde. Naja, ist ja egal, hauptsache jetzt geht's.

    Das mit dem Label-Text habe ich schon eingebaut gehabt, das habe ich nur nicht mit in die Frage genommen (hätte ich wahrscheinlich aus der Load_Pictures Methode auch rausnehmen sollen).
    Ich wollte auch nicht, dass es nach dem letzten Bild wieder von vorne losgeht, das passt mir nicht ins Konzept. Ich habe eher vor, dann eine Meldung auszugeben, dass das letzte Bild erreicht wurde oder so, aber dass muss ich mir noch mal durch den Kopf gehen lassen.

    Trotzdem vielen Dank für deine Mühen und Verbesserungsvorschläge.

    MfG biberiusmero

    Edit:
    Ich habe aus der Load_Pictures Methode die Anweisungen rausgenommen, die für mein Problem nicht relevant sind.

    Beitrag zuletzt geändert: 8.2.2015 10:25:12 von biberiusmero
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!