Я использую .NET4 WPF DataGrid для отображения таблицы SQL, содержащей много изображений.
Код XAML, о котором идет речь:
...
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Converter={StaticResource ImageConverter}, Path=Picture}" Stretch="Uniform" MaxHeight="200" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
...
И ImageConverter записывается кактакие:
[ValueConversion(typeof(Binary), typeof(BitmapImage))]
public class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = new System.IO.MemoryStream((value as Binary).ToArray());
bi.EndInit();
if (bi.CanFreeze) bi.Freeze();
return bi;
}
else return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
У меня вопрос, есть ли код выше утечки памяти?
Я пытался выполнить некоторые профилирования по этому поводу, но я не уверен, правильно ли я интерпретирую результаты.
Прежде всего, таблица SQL, содержащая изображения, использует 38 МБдисковое пространство (изображения должны храниться в формате png).После загрузки всех изображений в сетку данных через LINQ приложение использует около 170 МБ дополнительной оперативной памяти.Это, вероятно, может способствовать распаковке образов и тому факту, что сетка данных wpf является гигантским захватом памяти даже при включенной виртуализации.После закрытия окна использование памяти не падает.Повторное открытие окна приводит к использованию еще 170+ МБ ОЗУ, что делает общее использование памяти примерно 400 МБ.Если я снова открою окно, то использование памяти упадет до 330 МБ.Повторное открытие окна снова увеличивает объем используемой памяти до 380 МБ.Повторное открытие снова принимает его до 270 МБ.Повторное открытие снова приводит к 426 МБ.Так что, как вы можете видеть, очень нестабильно ...
Это небольшое тестирование было проведено с Win7 x64 и 8 ГБ оперативной памяти (приложение скомпилировано с опцией Любой процессор).
Я сделалПопробуйте тот же тест на виртуальной машине XP с <512 МБ оперативной памяти (около 384, если я правильно помню).И каждый раз, когда я снова открывал окно, я сначала видел резкое падение использования памяти, когда окно загружалось, а затем то же самое количество памяти использовалось повторно, поэтому общее использование было примерно одинаковым. </p>
Я интерпретирую эти результаты такчто ГХ не будет заниматься очисткой, если только подсистема памяти не будет сильно нагружена.Но в этом случае вызов GC.Collect () после закрытия окна должен освободить большую часть памяти?Единственное, что я не сделал, я увидел только снижение использования памяти на 4-6 МБ, когда я вызвал GC.Collect (я также попробовал все возможные параметры, включая принудительный сбор во всех поколениях и вызов GC.WaitForPendingFinalizers ()).
Это заставило меня задуматься о том, что, возможно, неиспользуемые утечки данных помещаются в файл подкачки.Но использование файла подкачки уменьшается и увеличивается в соответствии с использованием памяти равным образом.
Все вещи, которые здесь рассматриваются, не должны быть здесь утечкой памяти, но я не могу заставить использование памяти снижаться после того, как я закрылсяокно.Я пытался подключить к своему процессу какой-то профилировщик .NET, но эти профилировщики настолько сложны, что я не могу понять, живы ли показанные объекты изображений и на них ссылаются.Или они мертвы, и ГК просто не очистила их ...