Как получить доступ к объекту WPF в диспетчере? - PullRequest
0 голосов
/ 04 августа 2009

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

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

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

BackgroundWorker _bgWorker = new BackgroundWorker();

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

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

BitmapSource _tempBitmap = GetCaptchaFromServer();

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

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

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

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

Помощь будет принята с благодарностью!:)

Ответы [ 4 ]

5 голосов
/ 04 августа 2009

Просто вызовите 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 голосов
/ 05 августа 2009

@ Арктур, По моему опыту, если вы сделаете это, вы не получите никакой реакции на пользовательский интерфейс, пока загрузка с сервера не будет завершена ... потому что вы фактически прерываете поток пользовательского интерфейса, а затем загружаете материал ... я делал эту ошибку в пару моих projs и интересно, почему пользовательский интерфейс не отвечает ....

0 голосов
/ 04 августа 2009

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

Dispatcher.Invoke(DispatcherPriority.Background,
    new Action(() => { CaptchaBitmap = GetCaptchaFromServer(); } )
);
0 голосов
/ 04 августа 2009

У меня была такая же проблема WPF: передача объектов между потоком пользовательского интерфейса и фоновым потоком Не понял, что такое «правильное» решение. Закончилась замена моего BackgroundWorker на DispatcherTimer, который запускался только один раз, и это сработало.

...