2010-01-24 13 views
5

Sono un principiante con WPF e sto provando un progetto a casa per familiarizzare con la tecnologia. Ho una forma semplice in cui l'utente seleziona un file immagine, quindi visualizzo i dati EXIF ​​insieme a una miniatura dell'immagine. Funziona bene ma quando seleziono un file immagine RAW (~ 9 MB) ci può essere un leggero ritardo durante il caricamento del pollice, quindi ho pensato che avrei potuto usare il BackgroundWorker per decodificare l'immagine e l'utente può visualizzare i dati EXIF, quindi quando l'immagine è stata decodificata viene visualizzata.Problema WPF/BackgroundWorker e BitmapSource

L'oggetto BitmapSource è dichiarato nel metodo BackgroundWorkers DoWork:

worker.DoWork += delegate(object s, DoWorkEventArgs args) 
{ 
    string filePath = args.Argument as string; 

    BitmapDecoder bmpDecoder = BitmapDecoder.Create(new Uri(filePath), BitmapCreateOptions.None, BitmapCacheOption.None); 
    BitmapSource bmpSource = bmpDecoder.Frames[0]; 
    bmpSource.Freeze(); //As suggested by Paul Betts 

    args.Result = bmpSource; 
}; 

il problema che sto funzionando in è quando provo a impostare la fonte della mia controllo Image nel metodo RunWorkerCompleted ricevo un errore perché l'oggetto è di proprietà di un altro thread.

worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args) 
{ 
    imgThumb.Source = args.Result as BitmapSource; 
}; 

Ho provato ad utilizzare il metodo imgThumb.Dispatcher.BeginInvoke() per impostare la sorgente, ma questo non ha funzionato neanche, credo che sia perché è il args.Result che è di proprietà di un altro thread, e non il imgThumb? Come posso aggirare questo?

Potrebbe essere che stavo codificando il mio Dispatcher in modo errato (il seguente è dalla memoria, ho eliminato quello che avevo).

imgThumb.Dispatcher.Invoke(new Action<BitmapSource>(
    delegate(BitmapSource src) 
    { 
     imgThumb.Source = src; 
    } 
), bmpSource); 

Eventuali suggerimenti o idee sono benvenuti.

Aggiornamento

Modificato il mio metodo DoWork utilizzare BitmapCreateOptions.None piuttosto che .DelayCreation ma ora ottengo il seguente errore durante il caricamento di file RAW (file Canon .CR2 è tutto ciò che ho testato fino ad oggi), il il codice funziona bene per jpg. Potrebbe essere un problema con il Codec Canon che ho installato per permettermi di visualizzare i file RAW?

L'applicazione chiamati un'interfaccia che è stato marshalling per un diverso thread. (Eccezione da HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

risposta

8

chiamata Fermo() sul BitmapSource e non avrete questo problema (congelamento si libera delle restrizioni di threading, ma rende l'oggetto immutabile)

+0

Ho aggiunto la chiamata a Freeze() nel mio metodo DoWork, subito dopo aver impostato il valore di BitmapSource. Quindi aggiungo la seguente riga al metodo RunWorkerCompleted: BitmapSource xx = args.Result; che mi dà lo stesso errore di prima. Mi manca qualcosa di ovvio? Ho preso qualsiasi codice usando il Dispatcher. – Fermin

+0

Ero un idiota ma ora ho un diff. errore, domanda aggiornata. – Fermin

+0

Anche dopo molti anni. GRAZIE MILLE. cercavo tutto questo in rete – Kulpemovitz

2

Ho avuto esattamente il problema del campione ed è stato fortunato a risolverlo.

Risposta breve: avvolgerlo in WriteableBitmap. Questo ha un piccolo prezzo, tu.

Long answer.

+0

Per il mio caso, questa era l'unica soluzione che funzionava. Avevo bisogno di alimentare un BitmapFrame in un TransformedBitmap. Non ho avuto il controllo su quale thread è stato creato BitmapFrame poiché è fornito da una libreria (e la proprietà Dispatcher di BitmapFrame è null).Anche l'interrogazione della proprietà CanFreeze ha causato un'eccezione. Ho avuto due opzioni: revisione generale del mio codice sorgente e di altri, o uso di WriteableBitmap. Indovina quale ho scelto ... – elgonzo