c# – 在大型数据绑定ObservableCollection中添加/删除许多项而
我和我的团队正在开发一个
WPF应用程序,它显示了几个并发的XamDataChart控件(由Infragistics提供).每个图表都绑定到一个不同的ObservableCollection,最多可包含200万个点.对于每个图表,DispatcherTimer会定期检索要附加到集合的新项目(每100毫秒最多1000个).每次新项目到来时,它们都会被添加到集合的“尾部”,并且从“头部”移除相同的数量,以便集合中的项目数量在整个时间内保持不变.
我们面临的问题是添加/删除操作会冻结GUI,因为集合只能由主线程修改.我们已经尝试了很多方法(BackgroundWorker,Application.Current.Dispatcher with 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); })); } 提前致谢, 解决方法
在不了解更多关于您的场景的情况下很难知道正确的建议,因此我建议您将样本发布到Infragistics论坛并寻求帮助,如果您还没有这样做,如果您已经这样做,请回复链接到这个帖子,我会看看它.
如果您一次更新许多点作为单独的操作,那么使您的集合只引发一个事件而不是每个单独的事件会很有帮助.例如,如果您通过重复调用Add来更新集合的全部内容,则最好发送一个Reset事件,而不是所有单个事件.但似乎你已经在调用AddRange,我相信只会向图表发送一个通知. 如果您只有两个系列并且每100ms只更新一次,我不认为这会导致UI冻结,但是如果您有许多单独的系列,您将使用单独的调度程序交互单独更新数据,那么实际上会导致比你想要的更多的刷新图表. 图表将批量修改并限制刷新次数,但它使用调度程序执行此操作,因此如果您有15个不同的系列,您将在不同的时间间隔更新,并且所有系列都作为单独的调度程序thunks,那么您将导致更多对图表的更新比通过更新同一个调度程序thunk中的多个系列数据源来限制更新数量更新. 此外,如果您使用的是CategoryDateTimeXAxis,则在您的上述代码中,您可能会遇到目前在修改时对日期列进行排序的限制,这将以此规模谋杀您的表现.在这种情况下,我建议为该轴类型提交功能请求以支持预先排序的数据. 如果您的数据项支持INotifyPropertyChanged,但您没有使用它来通知图表的值更改,那么使用未实现INotifyPropertyChanged的项类型会好得多.如果您提交实现此接口的项目,则图表会假定它需要订阅此项以便收到更改通知(您可能永远不会打算这样做).这可能听起来不像是一个问题,但如果你有200万条记录,你正在高频率更新,那么很多事件订阅都是无意义的. 据我所知,图表在从属性绑定中检索值比使用字符串索引器要快得多,因此请确保它是一个简单的属性,而不是在MemberPath中的虚线属性路径. 希望这些信息对您有用.但是,使用可运行的样本诊断问题要容易得多,该样本提供了可能导致问题的所有上下文. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |