复杂 UI 的批量更新
我有一个非常复杂的 UI,其中有一个不断变化的状态栏,其中包含多种类型的状态消息,并且 UI 具有复杂的图表控件和加载的指示性地理地图。
现在,这些小而复杂的区域的数据上下文具有同样复杂的 ViewModel,例如 StatusBarVM、ChartingVM、GeoMapVM 等...它们实现了 INotifyPropertyChanged 和 ObservableCollections。
计算我的更新时,我发现我有大约 5000 个 UI 项目(标签、进度条、图表数据点、bgcolorsbrushes 等),这些项目正在以每秒 1000 个数据项更新的速度快速变化。
在 WPF UI 上实现批量数据更新的最佳方法是什么?
WPF 的绑定模型能够进行如此巨大的更新吗?如果是这样怎么办?因为我发现这对我来说并不是最佳选择。我也使用 bgworker(用于进度条)并使用 DIspatcher BeginInvoke...但要点是,即使如此,更新也会挂起 UI 线程,因为调度程序消息正在排队等待完成。
我无法实现虚拟化,因为状态是实时的,我必须在我面前的用户界面上看到它们。即使是几秒钟,我也不能错过它们(例如,不断变化的卫星地理数据)。
请帮助我确定正确的工具或某种方法来实现复杂但高度响应的 WPF UI。是 Dispatcher.PushFrame() 吗?
I have a very complex UI with a constantly changing status bar with multiple types of status messages and UI having a complex chart control and a indicative geographical map loaded.
Now the data context of these small but complex regions have equally complex ViewModels such as StatusBarVM, ChartingVM, GeoMapVM etc... They implement INotifyPropertyChanged and ObservableCollections.
Calculating my updates I see that I have around 5000 UI items (lables, progressbars, chart data points, bgcolorsbrushes etc.) which are changing at a speedy rate of 1000 data item updates per second.
What is the best way to achieve this bulk data update on a WPF UI?
Is WPF's binding model capable for such sort of huge updates? If so how? Because I see it isnt optimum in my case. I am using bgworker (for progressbars) as well and using DIspatcher BeginInvoke... but the point is that even then the updates do hang the UI thread as the dispatcher messages are getting queued up waiting to be finished.
I cannot implement virtualisation as the statuses are real time and I have to see them all on the UI in front of me.. I cannot afford to miss them even by a couple of second (e.g. constaly varying satellite's geographical data).
Please help me to identify a correct tool or some way to achieve a complex but highly responsive WPF UI. Is it Dispatcher.PushFrame()?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于每秒有如此多的更新,您将在队列中“备份”更新消息,这就是您的后台工作更新被阻止的原因。
要解决此问题,您需要限制抛出的更新事件的数量。
我将使用这样的方法:
在我的 ViewModel 中,将 INotifyPropertyChanged 的正常实现替换为对单例对象的调用,该对象将代表该对象发送通知。
其中propertyChanged是存储此对象事件处理程序的成员变量。
Notify
方法看起来像这样:在通知程序中,不立即发送事件 - 只需存储需要发送的事实。
如果您多次收到同一对象/属性的通知,请丢弃多余的通知。如果您多次收到同一对象但不同属性的通知,请将通知替换为 一个适用于所有属性。
现在,使用 UX 线程计时器每 50 毫秒左右“释放”一次通知 - 仍然足够快,用户不会注意到任何差异,它看起来像实时更新,但足够慢,可以检测(和删除)重复的通知。
With that many updates per second, you'll be getting update messages "backed up" in the queue, which is why your background worker updates are getting blocked.
To resolve this, you need to throttle the number of update events being thrown.
I'd use an approach like this:
In my ViewModels, replace the normal implementation of INotifyPropertyChanged with a call to a singleton object that will send the notification on behalf of that object.
Where
propertyChanged
is the member variable storing this objects event handlers.The
Notify
method would look something like this:Within the notifier, don't send the event immediately - just store the fact that it needs to be sent.
If you get notified multiple times for the same object/property, discard the extra notifications. If you get notified many times for the same object but different properties, replace the notification with a single one for all properties.
Now, use a UX thread timer to "release" the notifications every 50ms or so - still fast enough that the user won't notice any difference and it looks like real time updates, but slow enough to detect (and remove) duplicate notifications.