Frage

System: Windows XP SP3, .NET 3.5, 4 GB RAM, Dual 1,6 GHz

Ich habe eine WPF -Anwendung, die extrem große PNGs lädt und übergeht (mit Storyboard -Animationen). Diese PNGs sind 8190 x 1080 in Auflösung. Wenn die Anwendung ausgeführt wird, scheint sie die Bilder zu speichern und der Systemspeicher schleicht sich langsam an. Schließlich erstickt es das System und wirft die Ausnahme aus.

Hier sind die Schritte, die ich gerade mache, um dies zu lösen:

1) Ich entferne die Bitmapsource -Objekte aus der App

2) Ich setze die Bitmapsource -BitmapcacheOption auf keine, wenn ich die Bitmapsource lade

3) Ich friere die Bitmapsource ein, sobald sie geladen ist.

4) Ich lösche alle Verweise auf das Bild, das die Quelle sowie alle Verweise auf die Quelle selbst verwendet.

5) Manuell aufzurufen gc.collect (), nachdem die oben genannten Schritte abgeschlossen waren.

In der Hoffnung, herauszufinden, warum WPF für diese Bilder an den Speicher hängt, und eine mögliche Lösung, um sicherzustellen, dass der zum Laden verwendete Speicher ordnungsgemäß wiederhergestellt wird.

War es hilfreich?

Lösung

Sie haben sicherlich viel daran gearbeitet. Ich denke, das Hauptproblem ist, dass BitmapcacheOption.none nicht verhindert, dass die zugrunde liegenden BitmapDecoder (en) zwischengespeichert werden.

Es gibt mehrere knifflige Lösungen dafür, wie z.

Konstruieren Sie anstatt aus einem URI einen Stream und geben Sie ihn an den Konstruktor von Bitmapframe weiter:

var source = new BitmapImage();
using(Stream stream = ...)
{
  source.BeginInit();
  source.StreamSource = stream;
  source.CacheOption = BitmapCacheOption.OnLoad;    // not a mistake - see below
  source.EndInit();
}

Der Grund, warum dies funktionieren sollte, ist, dass das Laden aus einem Stream den Cache vollständig deaktiviert. Die obere Quelle ist nicht nur nicht zwischengespeichert, sondern auch keiner der internen Decoder wird zwischengespeichert.

Warum bitmapcacheOption.onload? Es scheint kontraintuitiv zu sein, aber diese Flagge hat zwei Effekte: Es ermöglicht das Caching, wenn das Caching möglich ist, und es führt zu einer Last am Endeinit (). In unserem Fall ist das Caching unmöglich, so dass alles, was die Last sofort erfolgt.

Offensichtlich möchten Sie diesen Code von Ihrem UI -Thread ausführen und dann die Bitmapsource einfrieren, damit Sie ihn übergeben können.

Sie können sich auch fragen, warum ich keine BitmapcreateOptions.IignoreImageCache verwendet habe. Abgesehen von der Tatsache, dass das Caching ohne UI unmöglich ist, ignoriert der IgnoreimerageCache den Bildcache nicht vollständig: Es ignoriert ihn nur zum Lesen. Selbst wenn IgnoreimerageCache eingestellt ist, wird das geladene Bild dennoch in den Cache eingefügt. Der Unterschied besteht darin, dass das vorhandene Bild im Cache ignoriert wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top