2010-03-11 13 views
5

Vorrei associare un'immagine a un tipo di controllo e cancellarla in seguito.Eliminazione di un'immagine utilizzata da un controllo WPF

path = @"c:\somePath\somePic.jpg" 
FileInfo fi = new FileInfo(path); 
Uri uri = new Uri(fi.FullName, UriKind.Absolute); 
var img = new System.Windows.Controls.Image(); 
img.Source = new BitmapImage(uri); 

Ora, dopo questo codice Vorrei cancellare il file:

fi.Delete(); 

ma non posso farlo in quanto l'immagine è in uso oggi. Tra frammento di codice 1 it 2 Cosa posso fare per rilasciarlo?

risposta

3

copiare l'immagine MemoryStream prima di dare per Imagesource dovrebbe assomigliare a questo

BitmapImage bi = new BitmapImage(); 
bi.BeginInit(); 
bi.DecodePixelWidth = 30; 
bi.StreamSource = byteStream; 
bi.EndInit(); 

dove Bytestream è copia del file in MemoryStream

anche this può essere utile

+2

Tx, funziona. Per i lettori successivi: l'ho copiato in un memorandtream come questo: MemoryStream byteStream = new MemoryStream (File.ReadAllBytes (path)); – Peter

+1

Sì, funziona **, ma è inefficiente ** perché: 1. Due copie dei dati dell'immagine vengono conservate per sempre e 2. La cache viene ignorata in modo che l'immagine venga caricata anche se è già nella RAM. L'articolo collegato spiega una soluzione alternativa per il # 1 ma richiede molto codice extra e comunque non risolve il # 2. Una soluzione molto migliore è 'BitmapCacheOption.OnLoad' combinato con' BeginInit/EndInit'. –

+0

Non puoi semplicemente chiudere il flusso di memoria dopo l'EndInit'? Perché dovresti tenere entrambi? – Jordan

11

Si potrebbe usare a MemoryStream ma che in realtà spreca memoria perché due copie separate dei dati bitmap sono conservate nella RAM: quando si carica il MemoryStream si effettua una copia e quando la bitmap viene decodificata viene creata un'altra copia. Un altro problema con l'utilizzo di MemoryStream in questo modo è che si ignora la cache.

Il modo migliore per farlo è quello di leggere direttamente dal file utilizzando BitmapCacheOptions.OnLoad:

path = @"c:\somePath\somePic.jpg" 

var source = new BitmapImage(); 
source.BeginInit(); 
source.UriSource = new Uri(path, UriKind.RelativeOrAbsolute); 
source.CacheOption = BitmapCacheOption.OnLoad; 
source.EndInit(); // Required for full initialization to complete at this time 

var img = new System.Windows.Controls.Image { Source = source }; 

Questa soluzione è efficiente e semplice troppo.

Nota: se si desidera ignorare la cache, ad esempio perché l'immagine potrebbe cambiare sul disco, è necessario impostare anche CreateOption = BitmapCreateOption.IgnoreImageCache. Ma anche in questo caso questa soluzione supera la soluzione MemoryStream perché non conserva due copie dei dati dell'immagine nella RAM.

+0

Suoni veramente buoni, ma sto ottenendo un: * Impossibile impostare lo stato di inizializzazione più di una volta. * A * source.BeginInit(); * – Peter

+0

Spiacente: non avevo testato il codice utilizzando quel particolare sovraccarico del costruttore. Sembra chiamare internamente "BeginInit()" e "EndInit()". Ho cambiato il codice per utilizzare il costruttore regolare, che dovrebbe risolvere il problema. –

+1

Altri problemi: 1. Non vedo Source come proprietà della classe BitmapImage 2. Se lo sostituisco con UriSource, continuo a capire che non è inizializzato ... Funziona anche se lo uso come questo : \t \t var source = new BitmapImage(); \t \t \t \t source.BeginInit(); \t \t \t \t source.UriSource = new Uri(path, UriKind.Absolute); \t \t \t \t source.CacheOption = BitmapCacheOption.OnLoad; \t \t \t \t source.EndInit(); +1 tuttavia per l'idea corretta, grazie. – Peter

Problemi correlati