2012-01-06 4 views
1

У меня есть 2 объекта NotificationObject, которые действуют как модели просмотра. Первый NotificationObject содержит свойства, привязанные к представлению определенного элемента управления, а второй NotificationObject имеет некоторый код, который выполняется в другом потоке с использованием объекта Thread. Мне нужно изменить свойства первого NotificationObject из текущего кода второго NotificationObject. Когда я пытаюсь это сделать, я получаю исключение. «Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток».a dispatcher для NotificationObject

Я думаю, что мне нужно использовать какой-то диспетчер для доступа к этим свойствам, как в Windows Forms или в классическом WPF, но я не могу найти, как это сделать в Prism MVVM. Итак, как мне изменить свойства первого NotificationObject?

ответ

4

Я предполагаю, что у вас есть что-то созданное в одном потоке и пытающееся обновить его из другого потока, и WPF этого не допускает. Объекты могут быть изменены только из потока, на котором они были созданы.

Обычно все объекты создаются в основном потоке пользовательского интерфейса, а Диспетчер используется для передачи асинхронных сообщений в поток пользовательского интерфейса для обновления этих объектов. Любая тяжелая обработка все еще может выполняться в фоновом потоке, однако для обновления свойства объекта вам нужно использовать основной поток пользовательского интерфейса.

Например, то, что выглядит, как это будет работать:

MyNotificationObject obj = new MyNotificationObject; 
obj.Items = MethodThatRunsOnBackgroundThread(); 

List<SomeObject> MethodThatRunsOnBackgroundThread() 
{ 
    var list = new List<SomeObject>(); 
    // Do Work 
    Return list; 
} 

В то время как это не будет:

MyNotificationObject obj = new MyNotificationObject; 
MethodThatRunsOnBackgroundThread(obj); 

void MethodThatRunsOnBackgroundThread() 
{ 
    var list = new List<SomeObject>(); 
    // Do Work 

    // This won't work since obj was created on UI thread 
    obj.Items = List<SomeObject>; 
} 

Вот еще один пример, который работает, потому что он посылает сообщение, чтобы обновить объект к потоку пользовательского интерфейса, который создал объект.

MyNotificationObject obj = new MyNotificationObject; 
MethodThatRunsOnBackgroundThread(obj); 

void MethodThatRunsOnBackgroundThread() 
{ 
    var list = new List<SomeObject>(); 

    // Load List 

    Application.Current.Dispatcher.BeginInvoke(DispatherPriority.Background, 
     new Action(delegate { 
      obj.Items = list; 
     })); 
} 
+0

Спасибо за ваши усилия, Рейчел, но я уже пробовал этот подход. Dispatcher.CurrentDispatcher.Invoke не работает. Я написал это как комментарий к ответу Баса B. –

+1

@ Bogdan0x400 Извините, синтаксис для этого неверен. 'Dispatcher.CurrentDispatcher' возвращает диспетчер для текущего потока, поэтому, если вы вызываете его из фонового потока, он возвращает диспетчера для фонового потока. Вам нужно вызвать его из UI thead, чтобы получить диспетчер для потока пользовательского интерфейса, или использовать что-то вроде 'Application.Current.Dispatcher'. 'App.Current.Dispatcher' - это синтаксис, который обычно наблюдается, поскольку приложение запуска проекта WPF по умолчанию называется' App'. Если ваш '' называется чем-то другим, вам придется использовать это вместо – Rachel

0

Application.Current.Dispatcher довольно много простое решение ..

В .NET 4.5 это, к счастью, не будет необходимости больше.

+0

Нет такой вещи, как Application.Current.Dispatcher, по крайней мере, в моем проекте. Вы имели в виду Dispatcher.CurrentDispatcher.Invoke? Я уже пробовал, но это вызвало такую ​​же ошибку. –

0

Пришлось искать объект UserControl для объекта Dispatcher, а не объект NotificationObject для представления модели. Я думаю, что неплохо ссылаться на представления из модельных представлений в MVVM, но я пока не нашел лучшего решения.

Смежные вопросы