Что такое кэширование данных изображения в моем приложении Silverlight 4? - PullRequest
1 голос
/ 18 мая 2011

Что-то держится за изображения в моем приложении 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>

1 Ответ

1 голос
/ 20 мая 2011

Я не уверен, почему это сработало, но я добавил следующий код к DownloadImage и память стабильна.

    /// <summary>
    /// Default C'tor
    /// </summary>
    public DownloadImage()
    {
        InitializeComponent();

        Unloaded += new RoutedEventHandler(OnUnloaded);
    }

    /// <summary>
    /// When the control is unloaded.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnUnloaded(object sender, RoutedEventArgs e)
    {
        BitmapImage bitmapImage = _image.Source as BitmapImage;
        if (bitmapImage != null)
        {
            bitmapImage.DownloadProgress -= new EventHandler<DownloadProgressEventArgs>(OnDownloadProgress);
            bitmapImage.ImageOpened -= new EventHandler<RoutedEventArgs>(OnDownloadSuccess);
            bitmapImage.ImageFailed -= new EventHandler<ExceptionRoutedEventArgs>(OnDownloadFailed);
        }

        _image.Source = null;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...