multithreadingWPF应用程序:Dispatcher Invoke。 一种更有效的方式?

使用.NET 3.5

嗨,大家好,我正在为一个项目制作一个WPF应用程序,我只是看看有关Dispatcher和multithreading的一些见解。 我的计划的一个例子:

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(Id, aList[i])))); Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action( () => _historical[0].Add(aList[i]))); 

据我所知,当另一个线程访问除创建它之外的对象时,WPF不喜欢。 然而,我认为必须有一个更好的方法,而不是让这么多的调度员调用,至少有人可以把我推向正确的方向(如果有更好的解决方案)。

干杯,Sparky

你可以从你的通话中减少冗长开始,即

 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]))); 

使用dispatcher.Invoke()实际上就是如何将操作返回到UI线程,这可能是首先创建这些对象(_aCollection)的地方。 如果有问题的项目没有与UI线程直接交互,那么您可以在不同的线程上创建/操作它们,从而无需使用调度程序。 当然,根据您的工作,这种方法可能会变得更加复杂。

最简单的方法是将所有三个调用合并为一个:

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

如果您使用.Net 4.0,我会考虑使用System.Threading.Tasks 。 这似乎是延续的一个主要例子。

您的问题源于事实,即ObservableCollection不会自动将更改分派给UI线程。 这与简单的INotifyPropertyChanged不同,它自动完成。 我建议创建自己的特定ObservableCollection,它实现INotifyCollectionChanged,自动调度UI线程的更改。

您可以在此处查看示例: SynchronizedObservableCollection和BindableCollection

旧答案/问题:您是否正在使用DependencyObject和DependencyProperties进行绑定? 如果是,那就放弃它。 它被多次讨论过,这是使用INotifyPropertyChanged的更大原因之一。 只需要使用调度程序就可以修改GUI对象本身的属性,而且从你的例子中可以看出,这不是你在做什么。 并且绑定本身通过调度程序自动运行。

另请参见视图模型:POCO与DependencyObjects