2009-08-04 2 views
0

Я использую шаблон MVVM для разработки приложения WPF.Как получить доступ к объекту WPF в диспетчере?

Приложение загружает изображение captcha с сервера и назначает его изображению в форме WPF при его готовности. Я использую BackgroundWorker сделать многопоточность для меня следующим образом:

Когда окно загружается, следующий называется:

BackgroundWorker _bgWorker = new BackgroundWorker(); 

_bgWorker.DoWork += GetCaptchaImage; 
_bgWorker.RunWorkerAsync(); 

Функция GetCaptchaImage довольно просто, загрузка изображения в другом потоке:

BitmapSource _tempBitmap = GetCaptchaFromServer(); 

Мне нужно знать, как вызвать Dispatcher присвоить этот ImageSource к источнику изображения моего окна, в настоящее время я называю диспетчеру после загрузки _tempBitmap следующим образом:

Application.Current.Dispatcher.Invoke(
new Action(() => CaptchaBitmap = _tempBitmap)); 

Где CaptchaBitmap находится в мой привязки данных источника изображения.

Однако, когда я делаю это, вызывается InvalidOperationException, и любая ссылка на _tempBitmap возвращает ошибку в потоке графического интерфейса пользователя . Я знаю его, потому что я обращаюсь к нему из диспетчера GUI thread, когда он был создан в потоке BackgroundWorker, но как я обойду его?

Справка была бы принята с благодарностью! :)

ответ

0

Просто из любопытства. Почему бы вам не сделать все извлечение и настройку изображения в потоке диспетчера вместо класса BackgroundWorker?

Dispatcher.Invoke(DispatcherPriority.Background, 
    new Action(() => { CaptchaBitmap = GetCaptchaFromServer(); }) 
); 
5

Просто позвоните BitmapSource.Freeze перед вызовом Dispatcher.Invoke

BitmapSource _tempBitmap = GetCaptchaFromServer(); 
_tempBitmap.Freeze(); 
Application.Current.Dispatcher.Invoke(
new Action(() => CaptchaBitmap = _tempBitmap)); 

объектов Всего WPF могут быть доступны только из потока, создавших их, исключение составляет Dispatcher (по понятным причинам) и Freezable после вы вызываете метод Freeze.

После вызова Freeze объект может быть доступен из любого потока (но не может быть изменен), к счастью для вас BitmapSource наследует от Freezable.

+0

Я отрывал свои волосы в течение последнего часа над этой проблемой. Спасибо, кучи! –

0

@Arcturus, Из моего опыта, если вы это сделаете, вы не получите никакой отзывчивости интерфейса до тех пор, пока загрузка с сервера не будет завершена ... потому что вы на самом деле перебиваете поток пользовательского интерфейса и ТОГДА загружаете материал ... я делал эту ошибку в нескольких своих проектах и ​​задавался вопросом, почему пользовательский интерфейс не отвечает ....

+0

Да, это правда .. вот почему я обычно делаю работу в фоновом потоке, так что поток пользовательского интерфейса получает наибольшее внимание и постоянно обновляется. – Arcturus