2008-10-09 6 views
5

J'ai un ListBox avec un tas d'images dedans (fait à travers un datatemplate). Les images sont créées en définissant la source des éléments:Disposer de l'image dans WPF dans Listbox (fuite de mémoire)

<Image x:Name="ItemImage" Source="{Binding ImageUrl}"/> 

puis ils sont effacés en utilisant la méthode Items.Clear() de la zone de liste. Les nouvelles images sont ajoutées en utilisant la méthode Items.Add de la zone de liste.

Cependant, l'utilisation de la mémoire commence à monter et à monter. Ce sont les mêmes 300 petites images qui sont affichées, mais la mémoire ne semble jamais être libérée. L'application commence à utiliser environ 40Megs, et grimpe rapidement jusqu'à 700Megs. Comment puis-je libérer la mémoire que toutes ces images utilisent?

EDIT: Une chose que j'ai oublié de mentionner, les images (qui font environ 4-5k de taille) sont en cours de chargement sur le réseau. La mise en cache est-elle en quelque sorte responsable de cela? Affichage 12 images mâche environ 10 Megs de mémoire, ce qui est d'environ 100X taille de fichier.

Répondre

4

Sauf si vous faites quelque chose d'inhabituel lors du chargement des images (comme utiliser des chargeurs d'images homebrewed ou quelque chose d'autre), le CPG devrait les effacer pour vous lorsque plus rien ne les référencera.

Conservez-vous des références aux données n'importe où? Rappelez-vous que les événements et les gestionnaires d'événements peuvent parfois « truc » le garbage collector en pensant qu'un objet est toujours utilisé:

MyObject obj = new MyObject(); 
obj.TheEvent += new EventHandler(MyHandler); 
obj = null; 
// Now you might think that obj is set for collection but it 
// (probably - I don't have access to MS' .NET source code) isn't 
// since we're still listening to events from it. 

Je ne sais pas si cela vaut pour vous, mais au moins c'est Étiez je vérifier si je étiez-vous. En outre, si vous avez accès à un profileur, tel que AQTime ou similaire, l'exécution de votre code peut vous donner quelques indications.

Vous pouvez également essayer de voir si cela fait une différence si vous chargez des images à partir d'un disque ou de ressources intégrées à votre assemblage.

4

Pourquoi ne pas utiliser toute cette mémoire en premier lieu?

(Note:. Le paragraphe et le code suivant sont reproduits à partir this answer)

Une partie du problème est qu'il est chargement de l'image complète dans chaque. Vous devez utiliser un IValueConverter pour ouvrir chaque image dans une taille de vignette en définissant les propriétés DecodePixelWidth ou DecodePixelHeight sur le BitmapImage. Voici un exemple que j'utilise dans l'un de mes projets ...

class PathToThumbnailConverter : IValueConverter { 
    public int DecodeWidth { 
     get; 
     set; 
    } 

    public PathToThumbnailConverter() { 
     DecodeWidth = 200; 
    } 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
     var path = value as string; 

     if (!string.IsNullOrEmpty(path)) { 

      FileInfo info = new FileInfo(path); 

      if (info.Exists && info.Length > 0) { 
       BitmapImage bi = new BitmapImage(); 

       bi.BeginInit(); 
       bi.DecodePixelWidth = DecodeWidth; 
       bi.CacheOption = BitmapCacheOption.OnLoad; 
       bi.UriSource = new Uri(info.FullName); 
       bi.EndInit(); 

       return bi; 
      } 
     } 

     return null; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { 
     throw new NotImplementedException(); 
    } 

} 

Vous pouvez également envisager IsAsync=True dans votre Binding de sorte que le convertisseur est appelé sur un thread d'arrière-plan.

+1

Ou mieux encore - utiliser la miniature intégrée si l'on existe si vous ne devez même pas lire le fichier entier et redimensionner ... Recherche BitmapFrame.Thumbnail –

+0

@xyzzer: Bon à savoir. –

+0

Le problème que j'ai vu est que ceux-ci viennent souvent avec des cadres noirs ou blancs dans la vignette, ce qui n'est pas toujours génial, je suppose que c'est pourquoi la plupart des navigateurs semblent construire leurs propres vignettes. –