2008-10-09 13 views
5

Ho un ListBox con un mucchio di immagini (fatto attraverso un datatemplate). Le immagini sono create impostando la fonte voci:Smaltire l'immagine in WPF in Listbox (perdita di memoria)

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

e poi vengono cancellati utilizzando il metodo Items.Clear() della casella di riepilogo. Le nuove immagini vengono aggiunte utilizzando il metodo Items.Add della listbox.

Tuttavia, l'utilizzo della memoria inizia appena a salire e salire e salire. Sono le stesse 300 o meno piccole immagini che vengono visualizzate, ma la memoria non sembra mai essere liberata. L'app inizia a utilizzare circa 40Megs e sale rapidamente fino a 700Megs. Come liberare la memoria che tutte queste immagini stanno utilizzando?

EDIT: Una cosa che ho dimenticato di menzionare, le immagini (che sono circa 4-5k ciascuna in dimensioni) vengono caricate in rete. Il caching è in qualche modo responsabile di questo? Visualizzazione di 12 immagini mastica circa 10 Meg di memoria, che è circa 100X di dimensione.

risposta

4

A meno che non si stia facendo qualcosa di insolito quando si caricano le immagini (come l'uso di caricatori di immagini homebrewed o qualcosa del genere), il GC dovrebbe cancellarle quando non le si fa più riferimento.

Sei aggrappato ai riferimenti ai dati ovunque? Ricordate che gli eventi e gestori di eventi a volte può "ingannare" il garbage collector a pensare che un oggetto è ancora in uso:

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. 

Non sono sicuro se questo vale per te, ma almeno questo è erano mi piacerebbe verificare se eri tu.

Inoltre, se si ha accesso a un profiler, ad esempio AQTime o simile, eseguire il codice attraverso di esso potrebbe fornire alcuni suggerimenti.

Si potrebbe anche provare e vedere se fa alcuna differenza se si caricano immagini da disco o da risorse incorporate nell'assieme.

4

Come non utilizzare tutta quella memoria in primo luogo?

(. Nota: il seguente paragrafo e il codice sono tratti da this answer)

Parte del problema è che sta caricando l'immagine completa in ciascuno. È necessario utilizzare IValueConverter per aprire ciascuna immagine in una dimensione di anteprima impostando le proprietà DecodePixelWidth o DecodePixelHeight su BitmapImage. Ecco un esempio che uso in uno dei miei progetti ...

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(); 
    } 

} 

Si può anche prendere in considerazione IsAsync=True nel vostro Binding in modo che il convertitore viene chiamato su un thread in background.

+1

O meglio ancora: utilizza l'anteprima incorporata se ne esiste una in modo da non aver nemmeno bisogno di leggere l'intero file e ridimensionarlo ... Lookup BitmapFrame.Thumbnail –

+0

@xyzzer: Buono a sapersi. –

+0

Il problema che ho visto è che spesso questi sono dotati di fotogrammi neri o bianchi come parte dell'anteprima, il che non è sempre eccezionale, suppongo che sia per questo che la maggior parte dei browser di immagini sembra creare i propri archivi di miniature. –