2017-06-13 7 views
3

Ich habe eine sehr einfache WPF-App, die verwendet wird, um Bilder in einem bestimmten Ordner Bild für Bild eine Vorschau zu zeigen. Sie können es sich als Windows Image Viewer-Klon vorstellen. Die App verfügt über ein PreviewKeyUp-Ereignis, mit dem das vorherige oder nächste Bild im Ordner geladen wird, wenn der Linkspfeil oder die Rechtspfeiltaste gedrückt wird.Speicherverlust beim Laden mehrerer Bilder in WPF vermeiden

Das Problem, das ich versuche zu lösen ist, dass es eine große Menge an Speicher aufgebläht wird, wenn mehrere Bilder geladen werden, bis Garbage Collection stattfindet. Sie können dies in dem Screenshot sehen, den ich von der Speicherbelegung der App gemacht habe. Es ist nicht ungewöhnlich, dass es 300 MB überschreitet, bevor die Garbage Collection stattfindet.

screenshot

Ich habe versucht, das Bild in einer using-Anweisung Einwickeln, aber das funktioniert nicht, weil Bitmap IDisposable nicht implementiert.

Was kann ich tun, um Speicherprobleme beim Laden mehrerer Bilder in meine App zu vermeiden?

+0

Sie auch bei dieser einen Blick nehmen möchten: https://stackoverflow.com/a/6271982/1136211 – Clemens

Antwort

5

Rufen Sie .Freeze() auf dem Bitmap-Objekt, das setzt es in einem schreibgeschützten Zustand und gibt einige der Punkte, die verhindert, dass es GC'ed wird.

Eine andere Sache, die Sie tun können, ist, dass Sie BitmapImage sagen können, Caching zu umgehen. Der Speicher, den Sie aufbauen, könnte aus dem Cache stammen.

CurrentImage.Source = new BitmapImage(new Uri(currentFile), 
            new RequestCachePolicy(RequestCacheLevel.BypassCache)); 

Schließlich, wenn es nicht eine Menge von Programmen auf dem Computer mit Putting Speichern Druck auf dem System .net ist erlaubt, so lange zu warten, wie es für einen GC will. Das Durchführen eines GC ist langsam und verringert die Leistung während des GC, wenn ein GC nicht erforderlich ist, da niemand den RAM anfordert und dann keinen GC ausführt.

3

Wenn Sie Vorschau sagen, brauchen Sie wahrscheinlich nicht die volle Bildgröße. Neben dem Aufruf von Freeze können Sie auch die Eigenschaft DecodePixelWidth oder DecodePixelHeight von BitmapImage festlegen.

Ich würde auch empfehlen, die Bilder direkt von einem FileStream anstelle von Uri zu laden. Beachten Sie, dass die Online-doc der UriCachePolicy sagt, dass es

... ein Wert ist, der die Caching-Richtlinie für Bilder darstellt, die von einer HTTP-Quelle stammen.

so könnte es nicht mit lokalen Datei Uris funktionieren.

auf der sicheren Seite zu sein, könnten Sie dies tun:

var image = new BitmapImage(); 

using (var stream = new FileStream(currentFile, FileMode.Open, FileAccess.Read)) 
{ 
    image.BeginInit(); 
    image.DecodePixelWidth = 100; 
    image.CacheOption = BitmapCacheOption.OnLoad; 
    image.StreamSource = stream; 
    image.EndInit(); 
} 

image.Freeze(); 
CurrentImage.Source = image; 
+1

würde ich vertrauen diese Antwort über meine, es ist eine Weile her, seit ich die Eigenheiten von BitmapImage herausfinden musste und es scheint viel frischer in Clemens 'Kopf zu sein. –

Verwandte Themen