В WPF MVVM как создать фоновую задачу, которая выполняет обратный вызов в потоке пользовательского интерфейса? - PullRequest
0 голосов
/ 21 августа 2009

Я знаком с объектом диспетчера элемента управления, но это не решает мою проблему в сценарии MVVM.

У меня есть команда пользовательского интерфейса, которая вызывает метод на моей виртуальной машине, который порождает поток и затем возвращает, когда поток завершен (фоновый работник может быть полезен для этого?), Он вызовет обратный вызов, но Хитрость в том, что обратный вызов изменяет наблюдаемую коллекцию, так как я могу вызвать этот обратный вызов в потоке пользовательского интерфейса?

Ответы [ 4 ]

4 голосов
/ 21 августа 2009

Используйте Dispatcher, связанный с потоком пользовательского интерфейса. Обычно у вас есть base ViewModel class , который выставляет Dispatcher для всех подклассов. Тогда ваша виртуальная машина будет делать что-то вроде:

Dispatcher.Invoke((ThreadStart) delegate
{
    //this code executes on the UI thread
});
1 голос
/ 21 августа 2009

Для этого отлично подойдет фоновый работник.

Что касается публикации вашего изменения в потоке пользовательского интерфейса, все, что вам нужно сделать, это привязать обратный вызов к вашему диспетчеру и использовать dispatcher.Invoke для фактического изменения наблюдаемой коллекции.

Вот почему почти всегда очень удобно, чтобы ваш класс ViewModel содержал ссылку на диспетчер. Это делает этот шаблон очень простым для реализации.

1 голос
/ 21 августа 2009

Если метод обратного вызова находится в форме или элементе управления с доступом к Диспетчеру, вы можете вызвать CheckAccess (). Если вы находитесь в одной теме, то просто делайте свою работу. В противном случае используйте диспетчер для отправки делегата в исполняющую функцию, которая затем будет в правильном потоке.

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

A BackgroundWorker было бы идеально для этого, потому что оно вызывает событие RunWorkerCompleted в соответствующем потоке на основе SynchronizationContext (который в WPF зависит от текущего диспетчера).

Другой вариант - сохранить текущий диспетчер (Dispatcher.CurrentDispatcher) перед выполнением асинхронной операции, чтобы вы могли использовать его для вызова обратного вызова.

Я написал класс для решения такого рода проблем для наблюдаемых коллекций, вы можете найти его здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...