2009-08-26 14 views
6

Sto cercando di capire come rilasciare una memoria WriteableBitmap.WPF WriteableBitmap Perdita di memoria?

Nella prossima sezione di codice riempio il backbuffer di un WriteableBitmap con una quantità molto grande di dati da "BigImage" (3600 * 4800 px, solo per il test) Se commento le linee in cui bitmap e immagine sono uguali a null, la memoria non è rilasciata e l'applicazione consuma ~ 230 MB, anche quando Immagine e bitmap non vengono più utilizzati!

Come è possibile vedere alla fine del codice è necessario chiamare GC.Collect() per rilasciare la memoria.

Quindi la domanda è, qual è il modo giusto per liberare la memoria utilizzata da un oggetto WriteableBitmap? GC.Collect() è l'unico modo?

Qualsiasi aiuto sarebbe fantastico.

PS. Scusa per il mio cattivo inglese.

private void buttonTest_Click(object sender, RoutedEventArgs e) 
{ 
      Image image = new Image(); 
      image.Source = new BitmapImage(new Uri("BigImage")); 

      WriteableBitmap bitmap = new WriteableBitmap(
       (BitmapSource)image.Source); 

      bitmap.Lock(); 

      // Bitmap processing 

      bitmap.Unlock(); 

      image = null; 
      bitmap = null; 

      GC.Collect(); 
} 
+0

http://stackoverflow.com/questions/1534983/how-to-dispose-a-writeable-bitmap-wpf/2422496#2422496 – nyxtom

risposta

0

Forzare un GC senza impostare image e bitmap a null non pulirli perché sono ancora in fase di riferimento a livello locale e sono quindi considerati riferimenti alla radice. Questo non ha nulla a che fare con lo WriteableBitmap e più una domanda su come funziona il GC.

Se non li si imposta su null e non imporre una garbage collection, questi verranno raccolti una volta che il metodo esiste e un GC si verifica. Questo è consigliato sopra forzando la raccolta da solo perché probabilmente stai danneggiando le prestazioni piuttosto che aiutarla.

+0

entrambi Grazie per il vostro aiuto. Il problema è che il garbage collector non sembra raccogliere la memoria usata da immagine e bitmap. Se commento le righe in cui sono assegnate a null e una volta che il metodo termina l'esecuzione, la memoria utilizzata dall'intera applicazione rimane ~ 234 MB. Sembra un comportamento davvero fastidioso. Grazie ancora. – Mario

+0

Resti per quanto tempo? Sei sicuro che il garbage collector stia effettivamente cercando di raccogliere? Apri perfmon e guarda i contatori GC per vedere se sta effettivamente cercando di raccogliere. In caso contrario, non hai nulla di cui preoccuparti: non c'è pressione di memoria, quindi il GC non è richiesto. –

+0

Grazie per il vostro aiuto e pazienza. Ho visto i contatori delle prestazioni GC, e c'è una bassa% di tempo trascorso in GC, però ho bisogno som aiuto per capire i dati successivo: #Bytes in tutti i cumuli di 1.115.176 mila #GC gestisce 845.000 #induce GC 5.0 Sembra che la chiamata a GC.Collect() non sia necessaria, ma l'assegnazione nullo di entrambi gli oggetti (immagine e bitmap) è, dal momento che quando vengono utilizzati la memoria utilizzata rimane a ~ 234 MB fino alla chiusura dell'applicazione. – Mario

1

In generale, la memoria dovrebbe essere liberata automaticamente secondo necessità.

Tuttavia, perché ciò accada, è necessario essere sicuri che l'oggetto sia veramente inutilizzato: nessun riferimento all'oggetto può esistere da nessuna parte, inclusi riferimenti che "non sono più utilizzati". Quindi, in particolare, se si posizionano WriteableBitmap e BitmapSource originale in variabili di una classe longeva, non verranno rilasciati fino a quando il contenitore non lo è.

Inoltre, WPF utilizza un modello GFX conservato: quando si esegue il rendering, si stanno effettivamente memorizzando le istruzioni su come renderizzare. Le "istruzioni" su come eseguire il rendering di una bitmap includono un riferimento alla bitmap, quindi se si esegue il rendering di una bitmap di grandi dimensioni, quindi per un po '(almeno finché è sullo schermo - anche se la versione sullo schermo è piccola) quelle le immagini saranno mantenute.

In pratica; memorizza i riferimenti a questi bitmap solo dove sono necessari e se il contesto in cui vivono è longevo (una lunga chiamata di metodo o una chiamata al metodo che genera una chiusura con un riferimento alle bitmap o un membro di una long- classe vissuta) quindi impostarli su null una volta che non sono più necessari.

Non è necessario liberare manualmente la memoria; GC.Collect() dovrebbe essere superfluo. Come regola generale, utilizzare GC.Collect durante l'analisi comparativa per ottenere un'indicazione del consumo di memoria e/o iniziare con una lavagna pulita. Le prestazioni generali sono generalmente diminuite dalle chiamate effettuate da GC.Collect().