Question

J'ai développé une application pour capturer et enregistrer des images à une base de données, mais je vais avoir un problème avec l'utilisation de la mémoire. Sur mon objet de domaine que j'ai 3 propriétés:

Image - tableau d'octets, le contenu est un jpg

RealImageThumb - Le tableau d'octets converti en un BitmapImage et rétracté, affiché à l'utilisateur dans un gridview avec d'autres vignettes

RealImage -. A pas poseur, le tableau d'octets convertis à une source de bitmap, ceci est représenté dans une info-bulle lorsque l'utilisateur plane sur elle

La question que j'ai est que si un utilisateur sur hovers chaque image tour à tour les spirales d'utilisation de la mémoire. Je réalise que comme plane de l'utilisateur par rapport aux sources bitmap sont générées et la mémoire n'a pas été libéré, j'ai essayé de donner RealImage une propriété de renforcement et attribuer cela à zéro après mais encore une fois la mémoire n'a pas été libéré (en attente de la poubelle collecteur?).

edit:

Est-ce que vous vouliez dire Ray? Je ne reçois rien montré dans l'infobulle comme ci-dessous, mais si je tente de définir un WeakReference<BitmapImage>, je reçois la System.WeakReference ne dispose pas d'erreur de paramètres de type.

  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;
            }
        }
Était-ce utile?

La solution

Vous devez faire trois choses:

  1. Lors de la construction de votre utilisation BitmapImage StreamSource pour fournir les données. Ne pas utiliser UriSource ou passer un Uri dans le constructeur, qui provoquerait l'image à ajouter au cache d'image.

  2. Dans la mise en œuvre RealImage de votre objet de domaine, stocker un WeakReference à votre BitmapImage pas le BitmapImage lui-même. Lorsque RealImage est tiré par les cheveux, si l'une ou WeakReference WeakReference.Target est null, créez un nouveau BitmapImage et une nouvelle WeakReference à lui.

  3. Utilisez un DataTrigger avec commutation de modèle pour inclure uniquement le contrôle de votre image dans l'arbre visuel quand il est visible

Voici les modèles nécessaires à l'étape 3, y compris celle avec le 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>

Maintenant, vous pouvez définir votre info-bulle comme ceci:

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

Comment ça marche: Il y a deux ContentPresenters unes dans les autres:

  • Lorsque la ContentPresenter externe est invisible, la ContentPresenter intérieure aura donc EmptyTemplate aucune image ne sera chargée.
  • Lorsque la ContentPresenter externe est visible, la ContentPresenter intérieure aura RealImageTemplate afin que l'image sera chargée et affichée.

La raison pour laquelle vous devez faire est qu'une info-bulle peut tenter d'optimiser les performances en ne disposant pas de la Popup une fois qu'il a été montré.

Mise à jour

Le code affiché pour RealImage doit travailler, et est presque exactement ce que je pensais. Je me suis rendu ce matin il n'y a vraiment pas besoin de mettre BitmapCacheOption ou BitmapCreateOption tant que personne ne SourceUri est spécifié. J'ai mis à jour ma réponse pour refléter cela et aussi de clarifier la chose WeakReference. Je corrige aussi un bug dans le modèle: je se lier à « RealImage » quand je liaient à « RealImage.Target »

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top