Отображение изображения из байтового массива в WPF - проблемы с памятью

StackOverflow https://stackoverflow.com/questions/3045843

Вопрос

Я разработал приложение для захвата и сохранения изображений в базу данных, но у меня есть проблема с использованием памяти. На моем доменном объекте у меня есть 3 свойства:

Изображение - байтовый массив, содержимое jpg

RealImageThumb - байтовый массив, преобразованный в растущее и сокращаемое, отображаемое пользователю в GridView с другими миниатюрами

RealImage - не имеет установки, байтовый массив преобразован в источник растрового изображения, это отображается в подсказке, когда пользователь охватывает его.

Проблема, которую у меня есть, это то, что если пользователь охватывает каждое изображение, в свою очередь, поверните спирали использования памяти. Я понимаю, что в качестве пользователей генерируются источники Bitmap, и память не освобождается, я попытался дать реализую поддержку свойства и присвоению этому нулю, но опять же, память не освобождается (ожидание мусора коллектор?).

редактировать:

Это то, что вы имели в виду луч? Я не получаю ничего, что показано на всплывающей подсказке, как показано ниже, но если я стараюсь определить WeakReference<BitmapImage>, Я получаю систему. WeakReference не имеет ошибки параметров типа.

  private WeakReference _realImage;
        public virtual BitmapImage RealImage
        {
            get
            {
                if (_realImage == null || _realImage.Target == null)
                {

                    if (Image == null) return null;
                    var newBitmapImage = new BitmapImage();
                    newBitmapImage.BeginInit();
                    newBitmapImage.CacheOption = BitmapCacheOption.None;
                    newBitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                    newBitmapImage.StreamSource = new MemoryStream(Image);
                    newBitmapImage.EndInit();
                    _realImage = new WeakReference(newBitmapImage);
                }

                return (BitmapImage)_realImage.Target;
            }
        }
Это было полезно?

Решение

Вам нужно будет делать три вещи:

  1. При строительстве вашего битового использования используйте Streamsource для подачи данных. Не используйте Urisource или не пропустите URI в конструктор, что приведет к добавлению изображения к кэше изображению.

  2. В реализации реализации объекта доменного объекта храните слабую визуализацию к вашему растрому, а не сам битмаписи. Когда RealImage выявляется, если либо слабовольская или слабоэкрана. Atarget - это NULL, создайте новое битовое использование и новую слабопривод к нему.

  3. Используйте DataTrigger с шаблонным переключением, чтобы включить только управление изображениями в визуальном дереве, когда он виден

Вот шаблоны, необходимые для шага 3, включая один с DataTrigger:

<DataTemplate x:Key="EmptyTemplate">
</DataTemplate>

<DataTemplate x:Key="RealImageTemplate">
  <Image Source="{Binding RealImage.Target}" Width="300" Height="300" />
</DataTemplate>

<DataTemplate x:Key="RealImageWhenVisible">

  <!-- Use EmptyTemplate when I am not visible -->
  <ContentPresenter x:Name="Presenter"
                    Content="{Binding}"
                    ContentTemplate="{StaticResource EmptyTemplate}"/>

  <!-- Switch to RealImageTemplate when I am visible -->
  <DataTemplate.Triggers>
    <DataTrigger Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}"
                 Value="True">
      <Setter TargetName="Presenter"
              Property="ContentPresenter.ContentTemplate"
              Value="{StaticResource RealImageTemplate}" />
    </DataTrigger>
  </DataTemplate.Triggers>
</DataTemplate>

Теперь вы можете определить свою всплеск, как это:

<Rectangle Width="40" Height="40" Fill="Blue">
  <Rectangle.ToolTip>
    <ContentPresenter Content="{Binding}"
                      ContentTemplate="{StaticResource RealImageWhenVisible}" />
  </Rectangle.ToolTip>
</Rectangle>

Как это работает: внутри друг друга есть два ContentPreesenters:

  • Когда внешний ContentPresenter невидим, внутренний ContentPresenter будет иметь joyTemplate, чтобы изображение не будет загружено.
  • Когда внешний ContentPreesenter виден, внутренний ContentPresenter будет иметь реамуметреэтметре, поэтому изображение будет загружено и отображено.

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

Обновлять

Код, который вы разместили для RealImage должны работать, и практически точно, о чем я думал. Этим утром я понял, что на самом деле нет необходимости устанавливать BitmapCacheOption или BitmapCreateOption, пока нет SourceUri. Я обновил свой ответ, чтобы отразить это, а также прояснить слабовение. Я также исправил ошибку в шаблоне: я привязал к «реалимаху», когда должен был быть обязательным с «RealImage.target».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top