如何添加上千项到绑定集合的无锁GUI [英] How to add thousands of items to a binded collection without locking GUI

查看:181
本文介绍了如何添加上千项到绑定集合的无锁GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我哪里有成千上万的潜在项目(3000-5000思)将被添加到的ObservableCollection 被绑定到一些视觉接口的设置。目前,加入他们的过程是相当慢(约4秒钟/ 1000项),当然在GUI在这段时间没有响应。什么是处理一次搬家,许多项目到一个集合,而不必担心系统锁定了一个好方法吗?我看了 DispatcherTimer ,但我不知道这是否会提供一切我需要它。

I have a setup where potentially thousands of items (think 3000-5000) will be added to an ObservableCollection that is binded to some visual interface. Currently, the process of adding them is quite slow (approx. 4 seconds/1000 items), and of course the GUI is unresponsive during that time. What is a good method to handle moving that many items at once into a collection without worrying about the system locking up? I've looked at DispatcherTimer but I'm not sure if it will provide everything I need it to.

另外一个问题 - 有什么我可以做,以加快这些对象的创建,使得它并不需要这么长时间将其添加到收藏?目前我使用它们像这样: Collection.Add(新项目(小于PARAMS>))会产生项目事前,在后台线程可能,减少所花费的时间?由一个明显的量将它们加入到

Another question - Is there something I can do to speed up the creation of these objects so that it doesn't take so long to add them to the collection? Currently I use them like so: Collection.Add(new Item(<params>)) Would generating the items beforehand, in a background thread probably, decrease the time it takes to add them by a noticeable amount?

编辑:虚拟化是不可能的。这些要求指定 WrapPanel 的样子,所以显示实际上是一个的ListBox 其中有一个模板ItemsPanel

Virtualization is not possible. The requirements specify a WrapPanel look, so the display is actually a ListBox which has a templated ItemsPanel

EDIT2:根据秒表,瓶颈实际上是把物品放入我的的ObservableCollection 。我会尝试改变这种集合类型,做我自己的通知,看看是否能大大加速它

According to the stopwatch, the bottleneck is actually putting items into my ObservableCollection. I will try changing that collection type and doing my own notification to see if that speeds it up substantially.

EDIT3:所以答案是在一个地方 - 我解决了这个问题, (从下帮助)通过创建从的ObservableCollection 继承的类。这个类做了两件事 - 公开一个方法来一次添加收藏,并添加到抑制 CollectionChanged 事件的能力。这些变化需要增添3000个项目的时间大约是0.4秒(97%的改善)。 的链接将详细介绍这些变化的实现。

So the answer is in one place - I solved this issue (with help from below) by creating a class which inherits from ObservableCollection. This class did two things - expose a method to add collections at one time, and added the ability to suppress the CollectionChanged Event. With these changes the time it takes to add 3000 items is roughly .4 seconds (97% improvement). This link details the implementation of these changes.

推荐答案

您说过1000,所以我会坚持这个数字只是实例。

You've said 1000, so I'll stick to that number just for instance.

IIRC,可观察到的集合有一个小缺点 - 如果你逐个添加的项目,它提出了按每个项目一次通知。这意味着,你有1000个通知项目1000和UI线程将在致命的速度运行,只是为了刷新屏幕跟上。

IIRC, the observable collection has a small drawback - if you add the items one by one, it raises notifies once per each item. That means that you have 1000 notifications for 1000 of items and the UI thread will run at deadly speed just to keep up with redrawing the screen.

你需要尽快重绘?也许你可以批量加有?拆分项目1000到包装的100个项目,或50个或20个项目多一点的包数。然后,而不是把所有的项目一个接一个,把他们的包。但要注意:你必须使用一些方法,如通过的AddRange收集它的自我实现,而不是由LINQ,否则你将再次有一个接一个插入。如果找到了这样的方法,它应该削减事件的数目显著,因为集合应该每的AddRange呼叫提高Changed事件一次。

Do you need to redraw ASAP? Maybe you can batch the additions? Split the 1000 of items into a few packed of 100 items, or a little more packets of 50 or 20 items. Then, instead of putting all items one by one, put them in packets. But beware: you have to use some methods like AddRange implemented by the collection it self, not by LINQ, or else you will again have one-by-one insertion. If you find such method, it should cut the number of events significantly, because the collection should raise the Changed event only once per AddRange call.

如果观察到的集合不具有的AddRange,既可以使用不同的收集,或者自己写,只是一个包装可能就足够了。我们的目标是在每一个Add()方法来不会引发Changed事件,但经过他们的合理数量,或者 - 也许只是跳过加入项目时提高和改变在某个固定的时间间隔改变募集?这将是有益的特别是,如果你的数据无限期地以恒定速率流入。

If observable collection does not have AddRange, either use different collection, or write your own, just a wrapper will probably be sufficient. The goal is to NOT raise Changed event at every single Add(), but after a reasonable count of them, or - maybe just skip raising Changed when items are added and raise Changed at some regular time intervals? This would be beneficial especially, if your data "flows in" indefinitely at a constant rate.

当然,在即将到屏幕上的一些物品,你可能只是以及在渲染它的自我举行。如果你的ItemTemplate很复杂,视觉层的实例的一个1000个对象的次1000 /属性可以简单地杀死了用户体验。 ?你有没有简化的ItemTemplate到最低限度。

Of course, at that number of items coming onto the screen, you may just as well be held at the rendering it self. If your ItemTemplates are complicated, a 1000 of objects times 1000 of instances of visual layers/properties may simply kill the user experience. Have you simplified the ItemTemplates to the bare minimum?

最后一件事:考虑使用虚拟化StackPanels在您的ItemsControl /列表框的ItemPanels。它可以大大减少内存占用,并在一个单一的时间点绘制的项目的数目。 !

Last thing: consider using virtualizing StackPanels as the ItemPanels in your ItemsControl/ListBoxes. It can greatly reduce the memory footprint and the number of items drawn at a single point of time. This will not necessarily help in the number or events raised, but it may help greatly when you have complex item templates!

编辑:您正在使用的ObservableCollection,所以我假定WPF / Silverlight的..更新的问题,如果这是不正确的。

you are using ObservableCollection, so I've assumed WPF/Silverlight.. update the question if this is not correct

这篇关于如何添加上千项到绑定集合的无锁GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆