Wie kann ich Form2, auf das nicht gewartet werden soll, disposen? (oder woher kommt diese Auslastung?)

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.

    Wie kann ich Form2, auf das nicht gewartet werden soll, disposen? (oder woher kommt diese Auslastung?)

    Hallo nochmal,

    ich habe ein neues Form, auf dem in voller Größe ein Bild angezeigt wird. Es soll nicht gewartet werden, bis es geschlossen ist. Leider füllt sich mit jedem Mal der RAM sehr deutlich. Wie kann ich das löschen?

    In dem Thread „Dialoge richtig instanziieren“ habe ich schon geschaut.

    In Form1, Aufruf von Form2

    VB.NET-Quellcode

    1. If CheckBox_TV.Checked AndAlso Screens.Count = 2 Then
    2. Await Task.Run(Sub() Erstelle_Form2())
    3. End If


    und

    VB.NET-Quellcode

    1. Public Sub Erstelle_Form2()
    2. '==================================================
    3. 'Erstellt eine Form, auf der das Bild zu sehen ist.
    4. 'Es wird absichtlich nicht .ShowDialog(Me) benutzt
    5. '(was man heute in VB.Net eigentlich macht), sondern
    6. ' .Show(Me), damit auf das Fenster nicht gewartet
    7. 'werden muss. Es ist komplett nebensächlich.
    8. '==================================================
    9. Dim Form2 As New Form_gross
    10. Dim W As Integer
    11. Dim H As Integer
    12. Using myBitmap As New Bitmap(file_path)
    13. W = myBitmap.Size.Width
    14. H = myBitmap.Size.Height
    15. End Using
    16. Me.Invoke(Sub() Form2.PictureBox1.Image = Image.FromFile(file_path))
    17. If W > 1848 OrElse H > 1006 Then
    18. Me.Invoke(Sub() Form2.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage)
    19. Else
    20. Me.Invoke(Sub() Form2.PictureBox1.SizeMode = PictureBoxSizeMode.Normal)
    21. End If
    22. 'Dim Dummy As DialogResult
    23. 'Me.Invoke(Sub() Dummy = Form2.Show())
    24. Me.Invoke(Sub() Form2.Show(Me))
    25. 'Debug.WriteLine(Dummy.ToString)
    26. 'End Using
    27. End Sub


    in Form 2

    VB.NET-Quellcode

    1. Public Class Form_gross
    2. Private Sub Button_rechtsrum_Click(sender As Object, e As EventArgs) Handles Button_rechtsrum.Click
    3. PictureBox1.Image.RotateFlip(RotateFlipType.Rotate90FlipNone)
    4. PictureBox1.Refresh()
    5. End Sub
    6. Private Sub Button_linksrum_Click(sender As Object, e As EventArgs) Handles Button_linksrum.Click
    7. PictureBox1.Image.RotateFlip(RotateFlipType.Rotate270FlipNone)
    8. PictureBox1.Refresh()
    9. End Sub
    10. Private Sub Button_Close_Click(sender As Object, e As EventArgs) Handles Button_Close.Click
    11. PictureBox1.Image = Nothing
    12. Close()
    13. End Sub
    14. Private Sub Form_gross_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    15. Me.Location = New Point(Screen.AllScreens(1).WorkingArea.Left, Screen.AllScreens(1).WorkingArea.Top)
    16. End Sub
    17. End Class

    Bartosz schrieb:

    In dem Thread „Dialoge richtig instanziieren“ habe ich schon geschaut.
    Du erstellst Form2 nebenläufig: Await Task.Run(Sub() Erstelle_Form2()), zeigst sie dann aber im Main-GUI-Thread an: Me.Invoke(Sub() Form2.Show(Me)).
    Beschreib mal ohne Code, was Du erreichen willst.
    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 möchte, dass auf einem zweiten Monitor eine Form2 erstellt wird, wo großflächig ein Bild erscheint. Das Hauptprogramm soll normal weiterlaufen. Irgendwann (nach Belieben) kann der Benutzer Form2 schließen.
    Das heißt, Form2 soll von Beginn an da sein, aber man soll sie nicht schließen müssen, damit das Programm weiter läuft.
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Und wozu brauchst Du das Ganze nebenläufig? Wenn Du mit Form2.Show arbeitest, kannst Du doch auf Form1 und Form2 rumhantieren, wie Du willst.
    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.

    Bartosz schrieb:

    aber man soll sie nicht schließen müssen
    Nimm einen nicht modalen Dialog: frm.Show(),
    wie @VaporiZed schon geschrieben hat.
    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!
    Und wozu brauchst Du das Ganze nebenläufig?
    Ich meinte damit das, was ich in Post 3 geschrieben habe. Das muss nicht asynchron heißen. Async habe ich nur während des Experimentierens geschrieben. :whistling:

    @ all: Das Problem ist, dass der Speicher nicht leerer wird, wenn die Form2 geschlossen wird.
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Ja genau. Arbeite also einfach ohne Umschweife mit Form2.Show und die Sache ist gegessen.

    ungetestet:

    VB.NET-Quellcode

    1. Dim Form2 As Form_gross = Nothing 'klassenweit deklarieren, sonst wird es in der unten angegebenen Sub erstellt und gleich zerstört
    2. '…
    3. If CheckBox_TV.Checked AndAlso Screens.Count = 2 Then
    4. Form2 = New Form_gross
    5. Dim W As Integer
    6. Dim H As Integer
    7. Using myBitmap As New Bitmap(file_path)
    8. W = myBitmap.Size.Width
    9. H = myBitmap.Size.Height
    10. End Using
    11. Form2.PictureBox1.Image = Image.FromFile(file_path)
    12. If W > 1848 OrElse H > 1006 Then
    13. Form2.PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage)
    14. Else
    15. Form2.PictureBox1.SizeMode = PictureBoxSizeMode.Normal)
    16. End If
    17. Form2.Show(Me)
    18. 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.
    @Bartosz Dann kannst Du im Form_Closing von Form2 den Inhalt der PictureBox explizit disposen.
    Setz6 allerdings einen Haltepunkt in die Dispose-Prozedur, ich denke, dasser da vorbeikommt.
    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!
    Danke euch beiden. Ich habe jetzt den Code von @VaporiZed benutzt und zusätzlich in Form_gross

    VB.NET-Quellcode

    1. Private Sub Form_gross_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
    2. PictureBox1.Image.Dispose()
    3. End Sub


    benutzt. Das ist schon viel besser als vorher. :thumbsup: Trotzdem sind's immer noch 4 MB mehr mit jedem Aufruf (also Form2-Entwurf im lfd. Programm). Aber ich denke, das ist nicht schlimm?
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Bartosz schrieb:

    Aber ich denke, das ist nicht schlimm?
    Steppe mal Dein Programm durch und stell fest, an welcher Stelle der Speicher alloziiert wird.
    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 denke auch nicht, dass das schlimm ist. Hast ja sicherlich n paar Gigabyte, oder?
    Aber interessant. Bei folgendem Code:

    VB.NET-Quellcode

    1. Public Class FrmMain
    2. Dim DummyForm As FrmMain
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. DummyForm = New FrmMain
    5. DummyForm.Show()
    6. End Sub
    7. End Class

    steigt mein Speicherverbrauch immer an, wenn ich über den Button.Click ein neues Form erstelle und dieses wieder schließe. Irgendwo verbleiben also im Speicher Überreste, die erst nach Programmabschluss freigegeben werden.
    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.
    OK, ich habe so exakt durchgesteppt, wie es geht.
    Zustand Nr.
    Aktionen
    1
    Es gibt für das Auswählen des Bildes einen Extra-Button.
    Nachdem das Bild ausgewählt wurde, endet der OpenFileDialog mit seinem End Using und das Programm hat 36,4 MB im Leerlauf.
    2
    Button_start wird geklickt,, Folgendes geschieht in der Sub "Erstelle_Form2()": im Using myBitmap habe ich 72 MB, nach
    Form2.PictureBox1.Image = Image.FromFile(file_path) ebenso, nach Form2.Show(Me) habe ich 75,5 MB.
    3
    Man sieht in den Diagnse-Tools, dass 2 Mal die Garbage-Collection angeworfen wurde. Vielleicht das Aufräumen des End Using myBitmap?
    Bild 2 16-22-33 Uhr
    Korrektur: restlichen Code auskommentiert. Es wird nun nicht mehr getan als Form2 erstellen. GC kommt nicht mehr vor. Speicher ist aber auch so hoch.
    4
    Form2 wurde über den Button geschlossen (sodass auch Form_gross_FormClosing mit dem .Dispose() geschieht). Programm hat 40,4 MB. Noch 4 MB mehr als am Anfang.

    hier mal der OFD-Code der Vollstädnigkeit halber.

    VB.NET-Quellcode

    1. Private Sub Button_auswaehlen_Click(sender As Object, e As EventArgs) Handles Button_auswaehlen.Click
    2. 'Bild auswählen
    3. Using OFD As New CommonOpenFileDialog
    4. OFD.Title = "Ein Bild auswählen"
    5. OFD.Filters.Add(New CommonFileDialogFilter("JPEG", ".jpg"))
    6. OFD.Multiselect = False
    7. OFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
    8. OFD.IsFolderPicker = False
    9. OFD.RestoreDirectory = False
    10. If OFD.ShowDialog() = DialogResult.OK Then
    11. file_path = OFD.FileName
    12. Else
    13. Return
    14. End If
    15. End Using
    16. End Sub

    Bilder
    • 2 16-22-33 Uhr - geschnitten - Kopie.jpg

      216,81 kB, 1.867×539, 66 mal angesehen
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()

    Wie geschrieben, ich gehe von nicht vermeidbaren Formüberresten aus.
    Öhm: Welche Bewandnis hat es mit den Zeilen#12-15? Da reicht: If OFD.ShowDialog() = DialogResult.OK Then file_path = OFD.FileName
    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.
    ich gehe von nicht vermeidbaren Formüberresten aus.
    Ok, dann lass ich das dabei.


    Welche Bewandnis hat es mit den Zeilen#12-15?
    Wenn der Benutzer nichts auswählt, dann soll das Programm nicht mit Nichts weitermachen. Wobei, wenn ich gerade drüber nachdenke...ich prüfe ja eh in Button_Start nochmal ab...hast Recht ^^

    VB.NET-Quellcode

    1. If System.String.IsNullOrEmpty(file_path) Then Return
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Dass Du das nochmal woanders prüfst, ist für diesen Codebereich irrelevant. Weil: Was passiert nach Z#10, wenn OK gedrückt wurde? Die Prozedur wird verlassen und der CommonOpenFileDialog wird disposed. Und wenn nicht OK gedrückt wurde? Es wird das Return ausgeführt. Wozu führt das? Die Prozedur wird verlassen und der CommonOpenFileDialog wird disposed. Also genau das gleiche! Daher ist der Else-Zewig komplett überflüssig. Würde zwischen Z#15 und Z#16 noch was anderes passieren, wär es ok, dass im Else-Zweig ein Return steht. Aber da Du geschrieben hast, dass dies der vollständige Code ist …
    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.
    @Bartosz Du erstellst die Bitmap-Instanz zwei Mal, ein Mal im Usung, ein Mal bei Image.FromFile().
    Wenn Du die Bitmap nur ein Mal erstellst, lass das Using weg und weise der Image-Property die Bitmap zu.
    Ist sichergestellt, dass im Designer der Image-Property nichts zugewiesen wurde?
    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!
    @RodFromGermany Finde ich gut, dass du darauf geachtet hast, allerdings brauche ich vorher die Werte für Breite & Höhe. Gibt es eine Möglichkeit, wo ich mir das

    VB.NET-Quellcode

    1. Using myBitmap As New Bitmap(file_path)
    2. W = myBitmap.Size.Width
    3. H = myBitmap.Size.Height
    4. End Using

    sparen kann?

    Ist sichergestellt, dass im Designer der Image-Property nichts zugewiesen wurde?
    Ich verstehe nicht ganz..also es kann jedes Bild sein, was der Benutzer anklickt. Daher kann es kein vordefiniertes Bild sein.
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    @Bartosz So was, ohne Using:

    VB.NET-Quellcode

    1. Dim myBitmap = New Bitmap(file_path)
    2. W = myBitmap.Width
    3. H = myBitmap.Height
    4. Form2.PictureBox.Image = myBitmap
    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!
    @RodFromGermany sorry für die späte Antwort. Muss ich mir am Wochenende anschauen.
    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.