Как избавиться от записываемого растрового изображения? (WPF) - PullRequest
8 голосов
/ 08 октября 2009

Некоторое время назад я опубликовал вопрос, связанный с утечкой памяти WriteableBitmap, и хотя я получил замечательные советы, связанные с этой проблемой, я все еще думаю, что есть серьезная ошибка / (ошибка, допущенная мной) / (Путаница) / ( Другое дело) здесь.

Итак, снова моя проблема:

Предположим, у нас есть приложение WPF с изображением и кнопкой. Источником изображения является действительно большое растровое изображение (3600 * 4800 пикселей), когда оно отображается во время выполнения, приложение занимает ~ 90 МБ.

Теперь предположим, что я хочу создать экземпляр WriteableBitmap из источника изображения (действительно большого изображения), когда это происходит, приложения потребляют ~ 220 МБ.

Теперь наступает сложная часть, когда изменения в изображении (через WriteableBitmap) заканчиваются, и все ссылки на WriteableBitmap (по крайней мере, те, которые мне известны) уничтожаются (в конце метода или установив их в нуль), память, используемая writeableBitmap, должна быть освобождена, а потребление приложения должно вернуться к ~ 90 МБ. Проблема в том, что иногда он возвращается, иногда нет.

Вот пример кода:

// The Image's source whas set previous to this event
private void buttonTest_Click(object sender, RoutedEventArgs e)
    {
        if (image.Source != null)
        {
            WriteableBitmap bitmap = new WriteableBitmap((BitmapSource)image.Source);

            bitmap.Lock();

            bitmap.Unlock();

            //image.Source = null;
            bitmap = null;
        }
    }

Как вы можете видеть, ссылка является локальной, и память должна быть освобождена в конце метода (или когда сборщик мусора решит это сделать). Однако приложение может потреблять ~ 224 МБ до конца юниверса.

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

1 Ответ

0 голосов
/ 11 марта 2010

Нужно ли рендерить растровое изображение с тем же разрешением и пикселями? Вы можете создать битовую карту для записи с гораздо меньшим набором пикселей и вызвать метод рендеринга. Так как при вызове рендеринга writeablebitmap содержит ссылку на исходные элементы, в этом случае у вас будет 3 блока: 1) исходный элемент, 2) пиксели в writeablebitmap, 3) ссылка на скопированный оригинал.

У меня была похожая проблема с writeablebitmap с точки зрения утечек памяти, и я исправил ее, проверив эту ссылку: http://www.wintellect.com/CS/blogs/jprosise/archive/2009/12/17/silverlight-s-big-image-problem-and-what-you-can-do-about-it.aspx

Если вы создадите еще одну карту битов с возможностью записи и скопируете пиксели, затем утилизируйте первую карту битов с возможностью записи, которую вы должны увидеть в памяти - по крайней мере, я это сделал в моем сценарии.

...