2010-01-24 7 views
5

Ich bin ein Anfänger mit WPF und versuche ein Heimprojekt, um sich mit der Technologie vertraut zu machen. Ich habe ein einfaches Formular, wo der Benutzer eine Bilddatei auswählt, dann zeige ich EXIF-Daten zusammen mit einer Miniaturansicht des Bildes an. Das funktioniert gut, aber wenn ich eine RAW-Bilddatei (~ 9 MB) wähle, kann es zu einer leichten Verzögerung beim Laden kommen, also dachte ich, ich könnte mit dem BackgroundWorker das Bild dekodieren und der Benutzer kann dann die EXIF-Daten sehen Wenn das Bild decodiert wurde, wird es angezeigt.WPF/BackgroundWorker und BitmapSource Problem

Das Bitmapsource Objekt wird in der BackgroundWorkers DoWork Methode deklariert:

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

das Problem, dass ich in laufen lasse, wenn ich versuche, die Quelle meiner Bildsteuerung in dem RunWorkerCompleted Verfahren einzustellen erhalte ich einen Fehler weil das Objekt einem anderen Thread gehört.

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

Ich versuchte, das imgThumb.Dispatcher.BeginInvoke() Verfahren unter Verwendung der Quelle einzustellen, aber dies hat nicht funktioniert entweder, ich denke, es ist, weil es die args.Result ist, die von einem anderen Thread gehört, und nicht die imgThumb? Wie kann ich das umgehen?

Es könnte sein, dass ich meinen Dispatcher falsch programmiert habe (der folgende ist aus dem Speicher, löschte ich, was ich hatte).

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

Alle Anregungen oder Ideen sind willkommen.

aktualisieren

meine DoWork Methode geändert BitmapCreateOptions.None zu verwenden, anstatt .DelayCreation aber jetzt bekomme ich folgende Fehlermeldung, wenn RAW-Dateien geladen werden (Canon CR2-Dateien ist alles, was ich bisher getestet haben), die Code funktioniert gut für JPGs. Könnte das ein Problem mit dem Canon Codec sein, den ich installiert habe, damit ich die RAW-Dateien anzeigen kann?

Die Anwendung genannt eine Schnittstelle, die für einen anderen Thread vermarshallten wurde. (Ausnahme von HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

Antwort

8

Anruf einzufrieren() auf der Bitmap und Sie werden dieses Problem nicht (Das Einfrieren der threading Einschränkungen entledigt, sondern macht das Objekt unveränderlich)

+0

Ich habe den Freeze() - Aufruf in meiner DoWork-Methode hinzugefügt, direkt nach dem Festlegen des BitmapSource-Werts. Ich füge dann der RunWorkerCompleted-Methode die folgende Zeile hinzu: BitmapSource xx = args.Result; Das gibt mir den gleichen Fehler wie zuvor. Fehle ich etwas Offensichtliches? Ich habe jeden Code mit dem Dispatcher herausgenommen. – Fermin

+0

Ich war ein Idiot, aber jetzt habe ich einen Unterschied. Fehler, aktualisierte Frage. – Fermin

+0

Auch nach vielen Jahren. VIELEN DANK. Ich habe das überall im Netz gesucht – Kulpemovitz

2

Ich hatte genau das Beispielproblem und hatte Glück, es zu lösen.

Kurze Antwort: wrap in WriteableBitmap. Das kommt zu einem kleinen Preis, thou.

Long answer.

+0

Für meinen Fall war dies die einzige Lösung, die funktionierte. Ich musste einen BitmapFrame in eine transformierte Bitmap einspeisen. Keine Kontrolle darüber, auf welchem ​​Thread der BitmapFrame erstellt wurde, da er von einer Bibliothek bereitgestellt wird (und die Dispatcher-Eigenschaft von BitmapFrame ist null).Selbst die Abfrage der CanFreeze-Eigenschaft verursachte eine Ausnahme. Ich hatte zwei Möglichkeiten: Generalüberholung des Quellcodes von mir und anderen, oder benutze WriteableBitmap. Rate mal welchen ich gewählt habe ... – elgonzo