Problema WPF/BackgroundWorker e BitmapSource
-
22-09-2019 - |
Pergunta
Sou iniciante no WPF e estou tentando um projeto doméstico para me familiarizar com a tecnologia.Eu tenho um formulário simples onde o usuário seleciona um arquivo de imagem e, em seguida, exibo os dados EXIF junto com uma miniatura da imagem.Isso está funcionando bem, mas quando eu seleciono um arquivo de imagem RAW (~9 MB), pode haver um pequeno atraso enquanto o polegar carrega, então pensei em usar o BackgroundWorker para decodificar a imagem e o usuário pode visualizar os dados EXIF, então quando a imagem for decodificada, ela será exibida.
O objeto BitmapSource é declarado no 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;
};
o problema que estou enfrentando é quando tento definir a origem do meu controle de imagem no método RunWorkerCompleted, recebo um erro porque o objeto pertence a outro thread.
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
imgThumb.Source = args.Result as BitmapSource;
};
Eu tentei usar o imgThumb.Dispatcher.BeginInvoke()
método para definir a fonte, mas também não funcionou, acho que é porque é o args.Result
que pertence a outro thread, e não ao imgThumb
?Como posso contornar isso?
Pode ser que eu estivesse codificando meu Dispatcher de forma errada (o seguinte é de memória, apaguei o que tinha).
imgThumb.Dispatcher.Invoke(new Action<BitmapSource>(
delegate(BitmapSource src)
{
imgThumb.Source = src;
}
), bmpSource);
Quaisquer sugestões ou ideias são bem-vindas.
Atualizar
Alterei meu método DoWork para usar BitmapCreateOptions.None em vez de .DelayCreation, mas agora recebo o seguinte erro ao carregar arquivos RAW (os arquivos Canon .CR2 são tudo que testei até o momento), o código funciona bem para jpg.Isso poderia ser um problema com o Canon Codec que instalei para permitir a exibição dos arquivos RAW?
O aplicativo chamou uma interface que foi organizada para um encadeamento diferente.(Exceção de HRESULT:0x8001010E (RPC_E_WRONG_THREAD))
Solução
Chame Freeze() no BitmapSource e você não terá esse problema (o congelamento elimina as restrições de threading, mas torna o objeto imutável)
Outras dicas
Eu tive exatamente o problema da amostra e tive sorte de resolvê-lo.
Resposta curta:embrulhar em WriteableBitmap
.Isso tem um pequeno preço, você.