2010-01-24 10 views
5

Soy un principiante con WPF y estoy intentando un proyecto casero para familiarizarme con la tecnología. Tengo un formulario simple donde el usuario selecciona un archivo de imagen, luego muestro datos EXIF ​​junto con una miniatura de la imagen. Esto funciona bien, pero cuando selecciono un archivo de imagen RAW (~ 9 MB) puede haber un ligero retraso mientras se carga el pulgar, así que pensé que podría usar el BackgroundWorker para decodificar la imagen y el usuario puede ver los datos EXIF, luego cuando la imagen ha sido decodificada, se muestra.Problema WPF/BackgroundWorker y BitmapSource

El objeto BitmapSource se declara en el método 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; 
}; 

el problema que estoy corriendo en es cuando intento configurar la fuente de mi control de imagen en el método RunWorkerCompleted recibo un error porque el objeto es propiedad de otro hilo.

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

He intentado utilizar el método imgThumb.Dispatcher.BeginInvoke() para establecer la fuente, pero esto no funcionó bien, supongo que es porque es la args.Result que es propiedad de otro hilo, y no el imgThumb? ¿Cómo puedo evitar esto?

Podría ser que estaba codificando incorrectamente mi Dispatcher (lo siguiente es de memoria, borré lo que tenía).

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

Cualquier sugerencia o idea es bienvenida.

actualización

cambiado mi método DoWork utilizar BitmapCreateOptions.None en lugar de .DelayCreation pero ahora me sale el siguiente error al cargar los archivos RAW (archivos de Canon .CR2 es todo lo que he probado hasta la fecha), la el código funciona bien para jpg's ¿Podría ser un problema con el Canon Codec I instalado para permitirme mostrar los archivos RAW?

La aplicación llamada una interfaz que fue marshalled para un hilo diferente. (Excepción de HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

Respuesta

8

Freeze Call() en el BitmapSource y usted no tendrá este problema (de congelación se deshace de las restricciones de roscado, pero hace que el objeto inmutable)

+0

Agregué la llamada Freeze() en mi método DoWork, justo después de establecer el valor de BitmapSource. Luego agrego la siguiente línea al método RunWorkerCompleted: BitmapSource xx = args.Result; que me da el mismo error que antes. ¿Me estoy perdiendo algo obvio? He eliminado cualquier código con el Dispatcher. – Fermin

+0

Estaba siendo un idiota pero ahora tengo un diff. error, pregunta actualizada – Fermin

+0

Incluso después de muchos años. MUCHAS GRACIAS. estado buscando esto en toda la red – Kulpemovitz

2

Tuve exactamente el problema de muestra y tuve la suerte de resolverlo.

Respuesta corta: envolver en WriteableBitmap. Eso tiene un pequeño precio, tú.

Long answer.

+0

Para mi caso, esta fue la única solución que funcionó. Necesitaba alimentar un BitmapFrame en un Transformed Bitmap. No tenía control sobre en qué subproceso se creó el BitmapFrame tal como lo proporciona una biblioteca (y la propiedad Dispatcher de BitmapFrame es nula).Incluso consultar la propiedad CanFreeze provocó una excepción. Tenía dos opciones: una revisión general del código fuente mío y otros, o usar WriteableBitmap. Adivina cuál elegí ... – elgonzo