【发布时间】:2012-07-23 14:19:42
【问题描述】:
我和我的团队正在开发一个显示多个并发 XamDataChart 控件的 WPF 应用程序(由 Infragistics 提供)。每个图表都绑定到一个不同的 ObservableCollection,最多可以包含 200 万个点。对于每个图表,DispatcherTimer 会定期检索要附加到集合的新项目(每 100 毫秒最多 1000 个)。每次有新项目出现时,它们都会被添加到集合的“尾部”,并从“头部”中移除相同的数量,这样集合中的项目数量就会随着时间的推移保持不变。
我们面临的问题是添加/删除操作正在冻结GUI,因为集合只能由主线程修改。我们尝试了很多方法(BackgroundWorker、Application.Current.Dispatcher 和 DispatcherPriority.Background、Task.Factory 等),但似乎都没有解决问题,而且 GUI 一直卡住。
您能否就处理大量绑定数据同时保持 GUI 响应速度的最佳方法向我们提供建议?
更新:
1) 正如我在下面的评论中所指出的,我们已经尝试在抑制 OnCollectionChanged 的同时添加和删除项目。即使它似乎对少量数据有效果,但在我们的场景中,这种解决方案的优势实际上是无法观察到的。
2) 数据在单独的线程中准备和收集。这是一个长时间运行的操作,但没有明显的缓慢或无响应。当数据被传递到图表组件进行渲染时,应用程序会冻结。
3) 以下是生成数据(在单独的线程中)并在 UI 上显示数据的方法:
private void GenerateDataButtonClick(object sender, RoutedEventArgs e)
{
Task<List<RealTimeDataPoint>> task = Task.Factory.StartNew(() => this.RealTimeDataPointGenerator.GenerateData(2000000));
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { this.DataPoints.Clear();
this.DataPoints.AddRange(task.Result);
if (!this.StartDataFeedButton.IsEnabled)
this.StartDataFeedButton.IsEnabled = true;
}));
}
public void DispatcherTimerTick(object sender, EventArgs e)
{
Task<List<RealTimeDataPoint>> task = Task.Factory.StartNew(() => this.RealTimeDataPointGenerator.GenerateData(1000));
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { this.DataPoints.RemoveRange(0, task.Result.Count); this.DataPoints.AddRange(task.Result); }));
}
提前致谢, 詹卢卡
【问题讨论】:
-
您可以创建一个派生自 ObservableCollection 的类,以便通知仅在一批更新结束后完成:stackoverflow.com/questions/9853064/…
-
@Bob:我们已经尝试抑制 OnCollectionChanged,直到添加和删除数据的批处理完成。不幸的是,这似乎对我们的场景有所帮助,因为必须显示大量的点。
-
看看 Reactive Extensions 怎么样? Here's 一个使用 Rx 和 M-V-VM 的示例(因此,一个 ObservableCollection),更具体地说是“ObserveOn”方法
-
@Ryan:感谢您的建议。我们正在挖掘它,因为它听起来很有趣。但是我不确定它是否是一个可行的解决方案,因为它依赖于外部库。
-
@GianlucaColucci 是的,至少它仍然是一个 Microsoft 库......由 msft 维护。但我理解这种犹豫。
标签: c# wpf infragistics