Утечка памяти в WPF WriteableBitmap? - PullRequest
6 голосов
/ 26 августа 2009

Я пытаюсь выяснить, как освободить память WriteableBitmap.

В следующем разделе кода я заполняю backbuffer WriteableBitmap действительно большим объемом данных из «BigImage» (3600 * 4800 px, только для тестирования) Если я прокомментирую строки, где растровое изображение и изображение равны нулю, память не освобождается, и приложение потребляет ~ 230 МБ, даже когда изображение и растровое изображение больше не используются!

Как вы можете видеть в конце кода, необходимо вызвать GC.Collect () для освобождения памяти.

Итак, вопрос в том, как правильно освободить память, используемую объектом WriteableBitmap? Является ли GC.Collect () единственным способом?

Любая помощь будет отличной.

PS. Извините за мой плохой английский.

private void buttonTest_Click(object sender, RoutedEventArgs e)
{
            Image image = new Image();
            image.Source = new BitmapImage(new Uri("BigImage"));

            WriteableBitmap bitmap = new WriteableBitmap(
                (BitmapSource)image.Source);

            bitmap.Lock();

            // Bitmap processing

            bitmap.Unlock();

            image = null;
            bitmap = null;

            GC.Collect();
}

Ответы [ 3 ]

3 голосов
/ 08 ноября 2009

Проводите ли вы свой тест на Windows XP, используя .Net 3.5 SP1? Если это так, то это известная проблема, которая будет исправлена ​​в 4.0.

См http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5d88cdf1-e992-4ad4-8f56-b5dbf92dcf1c

1 голос
/ 26 августа 2009

Как правило, память в конечном итоге должна автоматически освобождаться при необходимости.

Однако, чтобы это произошло, вы должны быть уверены, что объект действительно не используется: нигде не может быть ссылок на объект, включая ссылки, которые "больше не используются". Так, в частности, если вы поместите свой WriteableBitmap и оригинальный BitmapSource в переменные долгоживущего класса, они не будут освобождены, пока контейнер не будет.

Кроме того, WPF использует сохраненную модель GFX: при рендеринге вы просто сохраняете инструкции для как для рендеринга. «Инструкции» о том, как визуализировать растровое изображение, включают ссылку на растровое изображение - поэтому, если вы когда-либо будете рендерить большое растровое изображение, то какое-то время (по крайней мере, пока оно отображается на экране - даже если версия на экране мала) изображения будут сохранены.

На практике; храните ссылки на эти битовые карты только там, где они необходимы, и если контекст, в котором они живут, является долгоживущим (вызов метода long или вызов метода, генерирующий замыкание со ссылкой на битовые карты, или член long- класс жизни), затем установите их в нуль, как только они больше не нужны.

Нет необходимости вручную освобождать память; GC.Collect () должен быть лишним. Как правило, используйте GC.Collect только во время бенчмаркинга, чтобы получить представление об использовании памяти и / или начать с чистого листа. Общая производительность обычно снижается при вызовах do GC.Collect ().

0 голосов
/ 26 августа 2009

Принудительный сбор GC без установки image и bitmap на null не приведет к их очистке, поскольку на них все еще ссылаются локально, и поэтому они считаются корневыми ссылками. Это не имеет ничего общего с WriteableBitmap и больше вопросом о том, как работает GC.

Если вы не установите их на null и не будете принудительно собирать мусор, то они будут собраны, как только метод будет создан, и произойдет сборщик мусора. Это рекомендуется выше, форсировать коллекцию самостоятельно, потому что вы, скорее всего, ухудшаете производительность, а не помогаете ей.

...