Как освободить память после того, как BitmapImage больше не нужен?
Сначала я загружаю a BitmapImage
в элемент управления Image
на Window
.
Во-вторых, я работаю с элементом управления Image
, а затем закрою Window
.
Я делаю это 2-3 раза в минуту, и моя память заполняется очень быстро, потому что изображения не выгружаются обратно, когда окно закрыто.
Итак, как выгрузить BitmapImage
из Image.Source
управлять вручную, чтобы освободить память?
Ответы
Ответ 1
Я считаю, что решение, которое вы ищете, находится на http://www.ridgesolutions.ie/index.php/2012/02/03/net-wpf-bitmapimage-file-locking/. В моем случае я пытался найти способ удалить файл после его создания, но он, по-видимому, является решением обеих проблем.
Не освобождает память:
var bitmap = new BitmapImage(new Uri(imageFilePath));
Освобождает память и позволяет удалить файл:
var bitmap = new BitmapImage();
var stream = File.OpenRead(imageFilePath);
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
stream.Close();
stream.Dispose();
Дополнительно, также заморозить BitmapImage:
bitmap.Freeze();
Ответ 2
В моей ситуации кажется, что кэширование растрового изображения было проблемой. Я ранее загружал растровые изображения следующим образом:
Bitmap bitmap = new Bitmap();
using(var stream = new FileStream(...))
{
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
}
bitmap.Freeze();
image.Source = bitmap;
Постоянно заменяя image.Source
таким же образом, как только создала память, вручную принудительное удаление мусора не помогло.
Вместо этого отключение кэширования и использование этого потока (требуется оставить поток открытым до тех пор, пока изображение не будет отображено) в паре с ручной сборкой мусора устраняют сбор памяти для меня.
Stream mediaStream;
void DisposeMediaStream()
{
if (mediaStream != null)
{
mediaStream.Close();
mediaStream.Dispose();
mediaStream = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
}
}
void Update()
{
DisposeMediaStream();
var bitmap = new BitmapImage();
mediaStream = new FileStream(...);
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.None;
bitmap.StreamSource = mediaStream;
bitmap.EndInit();
bitmap.Freeze();
ControlImage.Source = bitmap;
}
Таким образом, я могу перебирать тонны изображений (например, Windows Photo Viewer), а память остается низкой. Обратите внимание, что поток не должен оставаться открытым, как только изображение действительно отображается.
Ответ 3
Вы можете установить объект в null
, чтобы объект BitmapImage больше не ссылался.
В этой ситуации GC должен позаботиться об освобождении ресурсов.
Вы можете вызвать GC.Collect
, но это может повлиять на производительность при слишком частом использовании.
Ответ 4
Вы можете вызвать Dispose()
на изображениях в окне Closed
. Я думаю, что также возможно оптимизировать объем памяти, используя различные варианты кеширования.
Edit:
Вы не можете вызвать Dispose(), вместо этого вы можете рассмотреть BitmapCacheOption.None
. Изображение будет считываться непосредственно с диска и не кэшироваться в памяти.