wie macht man Dispose?

  • VB.NET

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von jvbsl.

    wie macht man Dispose?

    Ich stelle einen Ausschnitt aus einem großen Bild in einer Picturebox dar und zeichne einige Linien darüber. Diesen Ausschnitt verschiebe ich mit der Maus. Dies führt früher oder später zu Speicherproblemen:

    Quellcode

    1. Sub Display()
    2. Dim DisplayMap As New Bitmap(PictureBox.Width, PictureBox.Height)
    3. Using gr = Graphics.FromImage(DisplayMap)
    4. gr.DrawImage(OriginalImage, -OffsetX, -OffsetY, OriginalImage.Width, OriginalImage.Height)
    5. gr.DrawLine(Pens.Red, 0, 0, 100, 200)
    6. gr.Flush()
    7. End Using
    8. PictureBox.Image = DisplayMap
    9. End Sub


    Nun wäre es eigentlich logisch, am Ende dieser Routine noch DisplayMap.Dispose() hinzuzufügen, aber dann funktioniert sie nicht mehr.

    Was kann ich tun, um den Speicherfehler zu vermeiden?
    naja PictureBox.Image enthält eine Referenz zu deiner DisplayMap und wenn du das Image neu setzt, dann brauchst du die alte DisplayMap nicht mehr, also musst du bevor du diese neu setzt das Alte entfernen, sofern denn bereits eins vorhanden ist
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Willkommen im Forum. :thumbup:

    Plenz schrieb:

    Nun wäre es eigentlich logisch, am Ende dieser Routine noch DisplayMap.Dispose() hinzuzufügen, aber dann funktioniert sie nicht mehr.
    Wwenn, dann musst Du das so machen:

    VB.NET-Quellcode

    1. If PictureBox.Image IsNot Nothing Then
    2. PictureBox.Image.Dispose
    3. End If
    4. PictureBox.Image = DisplayMap
    Das Bild, das angezeigt werden soll, darfst Du nicht disposen, sonst ist es weg.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!

    Neu

    Vielen Dank für die Erklärung. Leider fehlen mir bei Grafiken fundamentale Kenntnisse der Zusammenhänge. Ich hatte bisher gedacht, durch den Befehl "PictureBox.Image = DisplayMap" würde der Inhalt der Bitmap auf die Picturebox übertragen, und danach sollte die Bitmap eigentlich nicht mehr gebraucht werden. Die Sache funktioniert aber offensichtlich irgendwie völlig anders.

    Jedenfalls ist der Speicherfehler nicht mehr aufgetreten, seit ich deinen Befehl eingebaut habe. Vielen Dank!

    Neu

    das hat nichts mit Grafik ansich zu tun, sondern viel mehr mit Referenztyp vs Wertetyp.
    Bitmap ist ein Referenztyp.
    Wertetypen sind alle Primitivtypen(int/float/double/u.ä. sowie structs)
    Wertetypen werden immer kopiert und werden auf dem sogenannten Stack gehalten, also ein Stapelspeicher, der für die Ausführung von Programmen entscheidend ist.
    Referenztypen sind jedoch nur Verweise auf einen Speicherbereich an dem der eigentliche Wert steht.
    Wenn du also PictureBox.Image = bitmap; setzt, dann setzt du die Image referenz auf dein Bitmap, d.h. es ändert sich sogesehen nur die adresse von PictureBox.Image, welche genau dem Bitmap entspricht. Das heißt bitmap muss so lange im Speicher bleiben, bis keine der Referenzen zu diesem mehr vorhanden sind. Dein oben deklariertes Bitmap verliert bereits eine Referenz beim verlassen der Methode - in der Variable "bitmap". Jedoch hast du noch eine weitere Referenz in PictureBox.Image, weshalb du es noch nicht Disposen darfst.
    Also darfst du das Bitmap erst löschen, wenn du es nicht mehr anzeigen möchtest heißt, wenn PictureBox.Image einen neuen anderen Wert bekommt.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Neu

    jvbsl schrieb:

    sondern viel mehr mit Referenztyp vs Wertetyp
    Ist nicht ganz korrekt.
    Ein Struct kann als Element ein Bitmap enthalten, die ihrerseits disposed werden müsste.
    Hier geht es darum, ob ein Referenztyp unmanaged Speicher alloziiert und deswegen IDisposable implementiert.
    Der Garbage-Collector verwaltet und räumt auf managed Speicher, also Speicher, der unter .NET alloziiert wurde.
    Bei Verwendung von nativem Speicher muss man sich um das Aufräumen selber kümmern, der Garbage-Collector hat da keinen Zugriff.
    @Plenz Du hast hier sozusagen einen inversen Fall vorgestellt.
    Üblicherweise beschweren sich Hilfesuchende darüber, dass der Speicher vollllllllllläuft, weil sie das .Dispose() vergessen haben.
    Du hast vor Gebrauch aufgeräumt und Dein Bild gar nicht erst zu sehen bekommen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!

    Neu

    stimmt du hast recht eine struct könnte auch Disposable sein, daran hatte ich gar nicht gedacht. Wobei es am ende trotzdem wieder indirekt Referenztyp vs Wertetyp ist, nur dann eine Ebene tiefer :P
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---