VB.NET und Memory Leak bei PictureBox

Hallo!

Ich habe auf einer Form eine PictureBox. Während der Programmausführung kann der Benutzer durch viele verschiedenen Bilder, die auf der Festplatte vorliegen, navigieren.

Jetzt habe ich aber das Problem, das mit folgendem Code, die Größe des Programms im Arbeitsspeicher immer weiter wächst. Jedesmal wenn eine neue Grafik angezeigt wird, sieht man im Task-Manager, dass es wächst.

Was mache ich falsch? Vergesse ich auf etwas?

Public Sub GrafikAnzeigen(ByVal Element As Integer)
 'Dateiname aus Datenbank lesen
 Dim stDateipfad As String
 stDateipfad = DB.DateiName(Element)
 'Bild aus Datei laden
 Dim imBild As New Bitmap(stDateipfad)
 'Zoom bestimmen
 gbeBild.Breite = imBild.Width
 gbeBild.Höhe = imBild.Height
 pbBild.Height = Convert.ToInt32(gbeBild.Höhe \* (ZoomAuslesen() / 100))
 pbBild.Width = Convert.ToInt32(gbeBild.Breite \* (ZoomAuslesen() / 100))
 'Bild anzeigen
 pbBild.Image = imBild
End Sub

mfg
christoph

Hallo!
Du legst immer fleissig neue Bitmaps an, gibst sie aber nie frei.
Mach’ vor dem Zuweisen des neuen Bitmaps eine Abfrage, ob

pbBild.Image == null

ist und wenn nicht, dann ruf’

pbBild.Image.Dispose();

auf.

Dann dürfte der Speicher nicht mehr beliebig wachsen.

Gruß,
Martin

Hallo Martin!

Vielen Dank für deine Antwort. Ich habe deine Abfrage jetzt eingebaut, aber der läuft während der Ausführung nie hinein.

If pbBild.Image IsNot Nothing Then
 pbBild.Image.Dispose()
End If

Was ich aber beim testen jetzt gerade bemerkt habe: Wenn ich fleißig Bilder wechsle steigt der Speicherverbrauch bis über 300MB an und fällt dann plötzlich auf 50MB zurück. Danach geht es zwar mit jedem Bild wieder schrittweise hinauf, aber eben immer bei 300MB geht es hinunter.
Kann das irgendwie mit dem Garbage Collector zusammen hängen. Das der immer erst bei einer bestimmten Menge wegräumt?

mfg
christoph

Ja, das liegt am GC.

Der Garbage Collector prüft nach einiger Zeit (die Kriterien sind mir nicht bekannt) ob auf einen Speicherbereich noch zugegriffen werden kann.

Sprich: Du legst ein neues Bitmap an und die CLR lädt die Bitmap in den Speicher. Danach legst du eine neue Bitmap an und bindest diese an deine Klasse zB pbBild.

Läuft dein Programm weiter und du rufst ein neues Bild auf, so wird das neue Bitmap geladen. pbBild selbst ist aber nur eine Art Zeiger. pbBild ZEIGT als nur zuerst auf das eine und dann auf das andere Bild. Das gilt auch für die anderen Variablen in deinem Programm.

Wenn alle Variablen nicht mehr auf das alte Bild zeigen, so gilt für den GC, dass der Speicherbereich freigegeben werden kann.

Um den Speicher schneller (bzw. unverzüglich) freizugeben, versuche den Befehl pbBild.Dispose(true), dass signalisiert dem GC, dass du den Speicher ab sofort nicht mehr brauchst.

Grüße,

Alexander

Einen habe ich noch, nach kurzer Suche im Internet gefunden:

System.GC.Collect();

Zwingt den Garbage Collector den Speicher freizugeben. Anstatt sich von 18 auf 800 MB aufzublähen, verwendet meine Suchmaschine (lädt viele Daten, bearbeitet und speichert diese und soll dann Speicher freigeben) jetzt nur noch rund 20-22 MB Speicher, wenn ich den GC regelmäßig aufrufe.

Du könntest ihn aufrufen, nachdem die Bilder gewechselt wurden, dann sollte er den Speicher wieder freigeben und du musst nicht per Hand den Speicher jedesmal freigeben.

Grüße, Alexander.

1 Like

Hallo Alexander!

Nach meinem Urlaub bin ich erst jetzt zum Lesen deiner Antwort gekommen. Vielen Dank für den Tipp!

Mein Programm verbraucht jetzt nurmehr zwischen 30 und 40 MB. Das finde ich jetzt völlig in Ordnung.

mfg
christoph