Как вы убедитесь, что WPF выпускает большой Bitmapsource из памяти?

StackOverflow https://stackoverflow.com/questions/1684489

Вопрос

Система: Windows XP SP3, .NET 3.5, 4 ГБ ОЗУ, двойной 1,6 ГГц

У меня есть приложение WPF, которое загружает и переходы (с использованием анимаций раскадровки) чрезвычайно большие PNG. Эти PNG в разрешении 8190x1080. Когда приложение запускается, оно кажется кэшируя изображения, а системная память медленно ползет. В конце концов он задыхает систему и бросает OutofmemoryException.

Вот шаги, которые я сейчас предпринимаю, чтобы попытаться решить это:

1) Я удаляю объекты Bitmapsource из приложения

2) Я настраиваю Bitmapsource Bitmapcacheoption None, когда загружаю Bitmapsource

3) Я замерзаю растросию, как только он будет загружен.

4) Я удаляю все ссылки на изображение, которое использует источник, а также любые ссылки на сам источник.

5) Вручную вызов gc.collect () после завершения вышеупомянутых шагов.

В надежде выяснить, почему WPF висит на память для этих изображений, и возможное решение, чтобы убедиться, что память, используемая для их загрузки, правильно восстанавливается.

Это было полезно?

Решение

Вы, безусловно, проделали большую работу над этим. Я думаю, что основная проблема заключается в том, что Bitmapcacheoption.NONE не предотвращает кэширование основного ратмапдекодера.

В этом есть несколько сложных решений, таких как выполнение GC.Collect (), загрузка 300 небольших изображений из 300 различных URI и снова вызов GC.Collect (), но прост - это прост:

Вместо загрузки из URI просто постройте поток и передайте его конструктору Bitmapframe:

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

Причина, по которой это должно работать, заключается в том, что загрузка из потока полностью отключает кеш. Источник верхнего уровня не только кэширован, но и ни один из внутренних декодеров также не кэширован.

Почему Bitmapcacheoption.onload? Это кажется нелогичным, но этот флаг имеет два эффекта: он позволяет кэшировать, если возможно кэширование, и это приводит к возникновению нагрузки при Endinit (). В нашем случае кэширование невозможно, поэтому все, что он делает, приводит к тому, что нагрузка происходит сразу.

Очевидно, вы захотите запустить этот код с вашего потока пользовательского интерфейса, а затем заморозить Bitmapsource, чтобы вы могли перенести его.

Вы также можете задаться вопросом, почему я не использовал Bitmapcreateoptions.ignoreimagecache. Помимо того факта, что кэширование невозможно, без указания URI, игнорирование не полностью игнорирует кеш изображения: оно только игнорирует его для чтения. Таким образом, даже если будет установлено игнорирование, загруженное изображение все еще вставлено в кэш. Разница в том, что существующее изображение в кэше игнорируется.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top