Pregunta

He desarrollado una aplicación para capturar y guardar imágenes en una base de datos, pero estoy teniendo un problema con el uso de memoria. En mi objeto de dominio Tengo 3 propiedades:

Imagen - matriz de bytes, el contenido es un archivo JPG

RealImageThumb - La matriz de bytes convierte en un BitmapImage y encogido, se muestra al usuario en un gridview con otras miniaturas

RealImage -. No tiene setter, la matriz de bytes convertida a una fuente de mapa de bits, esto se muestra en una información de herramientas cuando los elementos emergentes del usuario sobre él

El problema que tengo es que si un usuario se desplaza sobre cada imagen a su vez los espirales uso de memoria. Me doy cuenta de que a medida que un usuario se desplaza sobre las fuentes de mapa de bits se generan y la memoria no se libera, lo he intentado dar RealImage una propiedad respaldo y asignarle a cero después pero de nuevo la memoria no se libera (en espera de la basura colector?).

editar

¿Es esto lo que quería decir Ray? Hasta ahora no recibo nada se muestra en la descripción de la siguiente manera, pero si lo intento y definen un WeakReference<BitmapImage>, me sale el System.WeakReference no tiene parámetros de tipo de error.

  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;
            }
        }
¿Fue útil?

Solución

Se tendrá que hacer tres cosas:

  1. Cuando la construcción de su uso BitmapImage StreamSource a suministrar los datos. No utilice UriSource o pasar un URI en el constructor, lo que causaría la imagen que se agrega a la caché de imágenes.

  2. En la aplicación RealImage de su objeto de dominio, almacenar un WeakReference a su BitmapImage no el propio BitmapImage. Cuando RealImage es exagerado, si bien WeakReference o WeakReference.Target es nula, crear un nuevo BitmapImage y un nuevo WeakReference a él.

  3. Utilice un DataTrigger con la plantilla de conmutación para incluir sólo el control de imagen en el árbol visual cuando es visible

Aquí son las plantillas necesarias para el paso 3, incluyendo el uno con el 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>

Ahora se puede definir su información sobre herramientas como esta:

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

¿Cómo funciona: Hay dos ContentPresenters uno dentro del otro:

  • Cuando el ContentPresenter exterior es invisible, la ContentPresenter interior tendrá EmptyTemplate así se cargará ninguna imagen.
  • Cuando el ContentPresenter exterior es visible, la ContentPresenter interior tendrá RealImageTemplate por lo que la imagen se carga y se muestra.

La razón por la que tiene que hacer esto es que una información sobre herramientas puede intentar optimizar el rendimiento al no disponer de la emergente una vez que se ha demostrado.

Actualizar

El código que envió para RealImage debe al trabajo, y es casi exactamente lo que estaba pensando. Me di cuenta esta mañana en realidad no hay necesidad de ajustar o BitmapCacheOption BitmapCreateOption, siempre y cuando no se especifica ningún SourceUri. He actualizado mi respuesta a reflejar esto y también para aclarar la cosa WeakReference. También he corregido un error en la plantilla: Estaba unión a "RealImage" cuando debería haber sido vinculante para "RealImage.Target"

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top