Многопоточное приложение WPF: Вызов диспетчера. Более эффективный способ?

использование .Net 3.5 с

Привет, ребята, я делаю приложение WPF для проекта, и я просто искал немного понимания относительно диспетчера и многопоточности. Пример моей программы:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () =>_aCollection.Add(new Model(aList[i], aSize[i]))));

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () => _Data.Add(new DataPoint<double, double>(Id, aList[i]))));

 Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () => _historical[0].Add(aList[i])));

Я понимаю, что WPF не нравится, когда другой поток обращается к объекту, отличному от того, который его создал. Тем не менее, я думал, что должен быть лучший способ, чем сделать так много вызовов диспетчера, может кто-нибудь, пожалуйста, подтолкнуть меня по крайней мере, в правильном направлении (если есть лучшее решение).

Ура, Спарки!--4-->

4 ответов


вы можете начать с того, что будете менее многословны в своих вызовах, т. е.

Application.Current.Dispatcher.Invoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));

еще один трюк, который я хотел бы использовать, чтобы сделать метод ярлыка, как это:

public static void UiInvoke(Action a)
{
  Application.Current.Dispatcher.Invoke(a);
}

тогда у вас еще меньше дел, как в:

UiInvoke(() =>_aCollection.Add(new Model(aList[i], aSize[i])));

через диспетчера.Invoke () - это действительно то, как вы возвращаете действие в поток пользовательского интерфейса, где, вероятно, эти объекты (_aCollection) были созданы в первую очередь. Если предметы не имеют прямого взаимодействия с UI thread, затем вы можете создавать / манипулировать ими в другом потоке, устраняя необходимость использования Диспетчера. Конечно, этот подход может стать более сложным в зависимости от того, что вы делаете.


самый простой способ объединить все три звонка в одно:

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(
                        () =>
                      {
                          _aCollection.Add(new Model(aList[i], aSize[i]);
                          _Data.Add(new DataPoint<double, double>(Id, aList[i]);
                          _historical[0].Add(aList[i])
                      }));

Если вы используете .Net 4.0, я бы посмотрел на использование


ваша проблема связана с тем, что ObservableCollection не автоматически отправляет изменения в поток пользовательского интерфейса. Это другая форма простой INotifyPropertyChanged, что делает его автоматически. Я бы рекомендовал создать свой собственный конкретный ObservableCollection, который реализует INotifyCollectionChanged, который автоматически отправляет изменения в поток пользовательского интерфейса.

вы можете увидеть пример здесь:SynchronizedObservableCollection и BindableCollection

старый ответ/вопрос: Вы используете DependencyObject и DependencyProperties для привязки? Если да, то отбросьте это. Это обсуждалось много раз, и это одна из больших причин, почему использовать INotifyPropertyChanged вместо. Только нужно использовать dispatcher для изменения свойств самих объектов GUI и его очевидного из вашего примера, это не то, что вы делаете. И обязательный сам запускается через диспетчера автоматически.

см. Также просмотр моделей: POCOs против DependencyObjects