Многопоточное приложение 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])
}));
ваша проблема связана с тем, что ObservableCollection не автоматически отправляет изменения в поток пользовательского интерфейса. Это другая форма простой INotifyPropertyChanged, что делает его автоматически. Я бы рекомендовал создать свой собственный конкретный ObservableCollection, который реализует INotifyCollectionChanged, который автоматически отправляет изменения в поток пользовательского интерфейса.
вы можете увидеть пример здесь:SynchronizedObservableCollection и BindableCollection
старый ответ/вопрос: Вы используете DependencyObject и DependencyProperties для привязки? Если да, то отбросьте это. Это обсуждалось много раз, и это одна из больших причин, почему использовать INotifyPropertyChanged вместо. Только нужно использовать dispatcher для изменения свойств самих объектов GUI и его очевидного из вашего примера, это не то, что вы делаете. И обязательный сам запускается через диспетчера автоматически.