Что-то держится за изображения в моем приложении Silverlight. Это проблема, потому что это приложение каталога с большим количеством изображений, которые пользователь может просматривать. Если пользователь просматривает каждую предоставленную библиотеку, приложению не хватит памяти и произойдет сбой. Я знаю, что это проблема с изображениями, потому что если я отключаю изображения, личный рабочий набор никогда не превышает 170 МБ. У меня есть пользовательский элемент управления (DownloadImage
), который показывает индикатор выполнения во время загрузки изображения. Это единственная вещь в моем коде, которая ссылается на BitmapImage
объекты. Я запустил профилировщик ( ANTS Memory Profiler 7.0 - хороший продукт, просто дав ему реквизиты ), и он показал, что все BitmapImage
экземпляры собираются правильно. Как и все экземпляры DownloadImage
элементов управления.
Вот код, стоящий за DownloadImage
:
public partial class DownloadImage : UserControl
{
public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached("Source", typeof(Uri), typeof(DownloadImage), new PropertyMetadata(null, OnSourcePropertyChanged));
/// <summary>
/// Default C'tor
/// </summary>
public DownloadImage()
{
InitializeComponent();
}
/// <summary>
/// D'tor
/// </summary>
~DownloadImage()
{
}
/// <summary>
/// Source - Image source.
/// </summary>
public Uri Source
{
get { return (Uri)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
/// <summary>
/// Initialize this DownloadImage with the given <see cref="BitmapImage"/> (<paramref name="a_bitmapImage"/>).
/// </summary>
/// <param name="a_bitmapImage">Given <see cref="BitmapImage"/>.</param>
public void Create(BitmapImage a_bitmapImage)
{
_noImage.Visibility = Visibility.Collapsed;
_image.Source = a_bitmapImage;
}
/// <summary>
/// Initialize this DownloadImage with the given image source <see cref="Uri"/> (<paramref name="a_imageSource"/>).
/// </summary>
/// <param name="a_imageSource">Given image source <see cref="Uri"/>.</param>
public void Create(Uri a_imageSource)
{
_noImage.Visibility = Visibility.Collapsed;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.CreateOptions = BitmapCreateOptions.DelayCreation | BitmapCreateOptions.IgnoreImageCache;
bitmapImage.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(OnDownloadProgress);
bitmapImage.ImageOpened += new EventHandler<RoutedEventArgs>(OnDownloadSuccess);
bitmapImage.ImageFailed += new EventHandler<ExceptionRoutedEventArgs>(OnDownloadFailed);
bitmapImage.UriSource = a_imageSource;
_image.Source = bitmapImage;
}
/// <summary>
/// When the download progress changes.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void OnDownloadProgress(object sender, DownloadProgressEventArgs e)
{
_progress.Visibility = Visibility.Visible;
_progress.Value = e.Progress;
}
/// <summary>
/// When the download succeeds.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void OnDownloadSuccess(object sender, RoutedEventArgs e)
{
_noImage.Visibility = Visibility.Collapsed;
_progress.Visibility = Visibility.Collapsed;
}
/// <summary>
/// When the download fails.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void OnDownloadFailed(object sender, ExceptionRoutedEventArgs e)
{
_noImage.Visibility = Visibility.Visible;
_progress.Visibility = Visibility.Collapsed;
}
/// <summary>
/// When SourceProperty dependency property changes.
/// </summary>
/// <param name="obj"></param>
/// <param name="e"></param>
private static void OnSourcePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
DownloadImage downloadImage = obj as DownloadImage;
if (downloadImage != null)
{
if (e.NewValue is Uri)
downloadImage.Create(e.NewValue as Uri);
else if (e.NewValue is BitmapImage)
downloadImage.Create(e.NewValue as BitmapImage);
else
return;
}
}
}
А вот и XAML:
<UserControl x:Name="userControl" x:Class="{Intentionally Left Blank}.DownloadImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:{Intentionally Left Blank}.Helpers"
xmlns:res="clr-namespace:{Intentionally Left Blank}.Resources"
xmlns:ee="http://schemas.microsoft.com/expression/2010/effects"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="100" Background="{StaticResource ImageBackground}">
<Grid x:Name="LayoutRoot" Background="{Binding Background, ElementName=userControl}">
<Viewbox HorizontalAlignment="Center" VerticalAlignment="Center" Margin="8">
<TextBlock x:Name="_noImage" TextWrapping="Wrap" FontSize="16"
res:Strings.Assignment="Text=DownloadImage.NoImage" Height="23" Width="79" Visibility="Collapsed">
<TextBlock.Foreground>
<SolidColorBrush Color="{StaticResource GrayLetters}"/>
</TextBlock.Foreground>
</TextBlock>
</Viewbox>
<Image x:Name="_image"/>
<ProgressBar x:Name="_progress" Height="15" VerticalAlignment="Bottom" Margin="1" Visibility="Collapsed"/>
</Grid>
</UserControl>