У меня есть несколько изображений, которые я загружаю в ListBox в моем приложении WPF. Первоначально я использовал GDI для изменения размеров изображений (оригиналы занимают слишком много памяти). Это было прекрасно, за исключением того, что они занимали около 400 мс на изображение. Не так хорошо. Поэтому в поисках другого решения я нашел метод, который использует TransformedBitmap (который наследуется от BitmapSource). Это здорово, подумал я, я могу это использовать. За исключением я теперь получаю утечки памяти где-то ...Утечка памяти при асинхронной загрузке изображений BitmapSource
Я загрузки изображения асинхронно с помощью BackgroundWorker так:
BitmapSource bs = ImageUtils.ResizeBitmapSource(ImageUtils.GetImageSource(photo.FullName));
//BitmapSource bs = ImageUtils.GetImageSource(photo.FullName);
bs.Freeze();
this.dispatcher.Invoke(new Action(() => { photo.Source = bs; }));
GetImageSource просто получает Bitmap с пути, а затем превращается в BitmapSource.
Вот фрагмент кода для ResizeBitmapSource:
const int thumbnailSize = 200;
int width;
int height;
if (bs.Width > bs.Height)
{
width = thumbnailSize;
height = (int)(bs.Height * thumbnailSize/bs.Width);
}
else
{
height = thumbnailSize;
width = (int)(bs.Width * thumbnailSize/bs.Height);
}
BitmapSource tbBitmap = new TransformedBitmap(bs,
new ScaleTransform(width/bs.Width,
height/bs.Height, 0, 0));
return tbBitmap;
Этот код, по существу код из: http://rongchaua.net/blog/c-wpf-fast-image-resize/
Любые идеи, что может быть причиной утечки?
редактировать: Вот код для GetImageSource, в соответствии с просьбой
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (var bmp = Image.FromStream(stream, false, false))
{
// Use WPF to resize
var bitmapSource = ConvertBitmapToBitmapSource(bmp);
bitmapSource = ResizeBitmapSource(bitmapSource);
return bitmapSource;
}
}
Как вы диагностировали утечку? И почему вы думаете, что это в этом коде, а не, например, GetImageSource()? –
BitmapSource, который я использую в элементе управления WPF, изменен правильно, но, глядя на память, используемую процессом, он использует ту же память, что и изображение полного размера. Поэтому где-то вдоль линии полноразмерный BitmapSource не удаляется. edit: и потому, что GetImageSource на самом деле не меняется. Если я захочу изменить размер с помощью GDI, это нормально. Но когда я изменяю размер с помощью этого метода TransformedBitmap, он не работает. – Harry
Не могли бы вы попросить ручной GC, чтобы узнать, выпущена ли память? Если нет, у вас, скорее всего, есть ссылка где-то, где хранится память. –