PictureBox.ImageLocation und Dispose

  • C#

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von dive26.

    PictureBox.ImageLocation und Dispose

    Moin Leute.
    Ich habe eine ListBox mit FileInfo-Instanzen von Bildern als DataSource.
    Im .SelectedIndexChange-Event wird das selektierte Bild in einer PictureBox[/tt] angezeigt.
    Verwende ich .Image = Image.FromFile(path) kann ich das Image der PictureBox disposen.
    Verwende ich .ImageLocation = path, knallt es beim zweiten Bild bei Application.Run(new MainForm()) => "ArgumentException - Ungültiger Parameter".
    Meine Frage:
    Braucht das PictureBox.Image bei Zuweisung über .ImageLocation nicht disposed zu werden?
    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    Laut Dekompilierungsprotokoll wird durch PicBox.WaitOnLoad = True die Image-Property der PicBox auch mit einer neuen Image-Instanz versehen. Ein DoppelDispose führt dann zu keinem Absturz (mehr). Ohne WaitOnLoad disposed Du die bestehende ImageInstanz und das führt dann zum Crash beim Festsetzen der ImageLocation, da das Image nicht mehr da ist. Aber das war Dir ja schon vorher klar.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Danke für Eure Rückmeldung.
    Bei Microsoft ist leider nichts dazu zu lesen, der IlSpy-Code war iwie schlecht nach zu verfolgen.
    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich befürchte gerade, dass da gar nix automatisch disposed wird, weil ich mit dem Code noch Zugriff auf das Bild hab. Oder der Testcode ist dumm:

    VB.NET-Quellcode

    1. Private F2 As New Form2
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    3. F2.ShowDialog(Me)
    4. F2.Dispose()
    5. Me.PictureBox1.Image = F2.PictureBox1.Image
    6. End Sub
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Das ist wahrscheinlich noch viel merkwürdiger.
    Ich hab im Dispose() Deiner Form2 ein PictureBox1.Dispose() eingefügt und das ganze funktioniert immer noch.
    Erst bei PictureBox1.Image.Dispose() knallt es in der Zeile Me.PictureBox1.Image = F2.PictureBox1.Image.
    Es sieht so aus, als gäbe es da ein "Schatten-Image".
    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich hab da mal was probiert. Es ist wie in einem VS-Issue beschrieben: Die Bilder bleiben und fressen Speicher.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles bt_ok.Click
    3. Using Dialog As New Form2
    4. Dialog.ShowDialog(Me)
    5. End Using
    6. End Sub
    7. End Class

    VB.NET-Quellcode

    1. Public Class Form2
    2. Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. For i = 1 To 100
    4. Dim NewPicBox As New PictureBox With {.Image = My.Resources.Profilbild}
    5. FlowLayoutPanel1.Controls.Add(NewPicBox)
    6. Next
    7. End Sub
    8. End Class


    Bei jedem Klick steigt und steigt der Speicherbedarf des Programms.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Bei jedem Klick steigt und steigt auch dort der Speicherbedarf des Programms, trotz Formschließung. Nicht so sehr wie bei der Resources-Methode, aber ich bin seit Post#5 ja auch gedanklich bei "Images werden nach der Form- und PicBox-Entsorgung nicht entsorgt."
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Möglicherweise liegt das daran, dass Speicherbereiche für Bilder zumindest partiell unmanaged sind und daher stiefmütterlich behandelt werden.
    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).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich hatte auch das Problem bei diversen Anwendungen.
    Bilder die direkt in die Picturebox geladen wurden waren gelockt.
    Auch wenn man diese disposed hat, dann wurde der Speicher bei jedem neuen Laden trotzdem immer voller.

    Nun lade ich das Image in ein IMAGE, kopiere dies und dispose das IMAGE wieder.
    Die Kopie liegt nun im Speicher (ohne Dateilock) und kann einer Picturebox zugewiesen werden.
    Bevor ich der Picturebox so ein neues Bild zuweise, dispose ich das alte Bild in der Picturebox und dispose auch das image Objekt.
    Auf die Schnelle habe ich nur diesen Code hier in meinen Quellcodes gefunden:

    VB.NET-Quellcode

    1. Try
    2. PictureBox_Produktfoto.Image = Nothing
    3. If File.Exists(ProduktBildDateiname) Then
    4. PictureBox_Produktfoto.SizeMode = PictureBoxSizeMode.Zoom
    5. Dim HilfsBild As Image = System.Drawing.Image.FromFile(ProduktBildDateiname)
    6. Dim newBit As New Bitmap(HilfsBild.Width, HilfsBild.Height)
    7. Using g As Graphics = Graphics.FromImage(newBit)
    8. g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
    9. g.DrawImage(HilfsBild, 0, 0, HilfsBild.Width, HilfsBild.Height)
    10. End Using
    11. If PictureBox_Produktfoto.Image IsNot Nothing Then PictureBox_Produktfoto.Image.Dispose()
    12. PictureBox_Produktfoto.Image = newBit
    13. HilfsBild.Dispose()
    14. Else
    15. PictureBox_Produktfoto.SizeMode = PictureBoxSizeMode.CenterImage
    16. PictureBox_Produktfoto.Image = My.Resources.foto
    17. End If
    18. Catch ex As Exception
    19. MsgBox(ex.Message)
    20. End Try


    Oder das Bildladen als Funktion:

    VB.NET-Quellcode

    1. Public Function LoadUnlockedPicture(datei As String) As Image
    2. Dim xx As Image
    3. Using str As Stream = File.OpenRead(datei)
    4. xx = Image.FromStream(str)
    5. End Using
    6. LoadUnlockedPicture = xx
    7. End Function
    8. Public Shared Function GetMemoryBitmapFromFile(path As String) As Bitmap
    9. Dim bm As Bitmap
    10. Using img As Image = Image.FromFile(path)
    11. bm = New Bitmap(img)
    12. End Using
    13. Return bm
    14. End Function
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at