使用.NET 3.5
嗨,大家好,我正在为一个项目制作一个WPF应用程序,我只是看了一下Dispatcher和多线程的一些见解。我的计划的一个例子:
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不喜欢。但是,我认为必须有一个更好的方法,而不是让这么多的调度员调用,至少有人请你把我推向正确的方向(如果有更好的解决方案)。
干杯, Sparky的
答案 0 :(得分:15)
你可以从你的电话中减少冗长开始,即
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线程直接交互,那么您可以在不同的线程上创建/操作它们,从而无需使用调度程序。当然,这种方法可能会变得更加复杂,具体取决于您正在做什么。
答案 1 :(得分:13)
最简单的方法是将所有三个调用合并为一个:
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])
}));
答案 2 :(得分:6)
如果您使用.Net 4.0,我会考虑使用System.Threading.Tasks。这似乎是continuations的一个主要示例。
答案 3 :(得分:2)
您的问题源于事实,ObservableCollection不会自动将更改分派给UI线程。这与简单的INotifyPropertyChanged不同,它自动完成。我建议创建自己的特定ObservableCollection,它实现INotifyCollectionChanged,自动调度对UI线程的更改。
您可以在此处查看示例:SynchronizedObservableCollection and BindableCollection
旧答案/问题: 您使用DependencyObject和DependencyProperties进行绑定吗?如果是,则放弃它。它被多次讨论过,这是使用INotifyPropertyChanged代替的更大原因之一。只需要使用调度程序就是修改GUI对象本身的属性而且从你的例子中可以明显看出,这不是你在做什么。绑定本身通过调度程序自动运行。