我有一个设置,其中可能有数千个项目(认为 3000-5000 个)将添加到ObservableCollection
绑定到一些可视化界面。目前,添加它们的过程非常慢(大约 4 秒/1000 个项目),当然 GUI 在此期间没有响应。有什么好方法可以一次性将这么多项目移动到集合中而不用担心系统锁定?我看过DispatcherTimer
但我不确定它是否能提供我需要的一切。
另一个问题 - 我可以做些什么来加快这些对象的创建速度,这样就不需要花很长时间将它们添加到集合中?目前我像这样使用它们:Collection.Add(new Item(<params>))
在后台线程中预先生成这些项目可能会显着减少添加它们所需的时间吗?
编辑:虚拟化是不可能的。要求指定了WrapPanel
看,所以显示器实际上是一个ListBox
其中有一个模板化的 ItemsPanel
Edit2:根据秒表,瓶颈实际上是将项目放入我的ObservableCollection
。我将尝试更改该集合类型并执行我自己的通知,看看是否会显着加快速度。
Edit3:所以答案就在一个地方 - 我通过创建一个继承自的类解决了这个问题(在下面的帮助下)ObservableCollection
。这个类做了两件事 - 公开一种一次性添加集合的方法,并添加了抑制CollectionChanged
事件。通过这些更改,添加 3000 个项目所需的时间大约为 0.4 秒(改进了 97%)。This http://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/链接详细介绍了这些更改的实施。
你说的是 1000,所以我就以这个数字为例。
IIRC,可观察集合有一个小缺点 - 如果您逐个添加项目,它会为每个项目引发一次通知。这意味着您有 1000 个项目的 1000 个通知,并且 UI 线程将以致命的速度运行,只是为了跟上屏幕的重绘。
需要尽快重画吗?也许你可以批量添加?将 1000 件物品分成几包,每包 100 件,或多包,每包 50 件或 20 件。然后,不要将所有物品一件一件地放入,而是将它们放入包装袋中。但要注意:您必须使用集合本身实现的 AddRange 等方法,而不是 LINQ,否则您将再次进行一对一插入。如果您找到这样的方法,它应该会显着减少事件的数量,因为集合应该在每次 AddRange 调用时仅引发一次 Changed 事件。
如果可观察集合没有 AddRange,要么使用不同的集合,要么编写自己的集合,仅一个包装器可能就足够了。目标是不在每个 Add() 处引发 Changed 事件,而是在合理计数之后引发 Changed 事件,或者 - 也许只是在添加项目时跳过引发 Changed 事件并在某些固定时间间隔引发 Changed 事件?如果您的数据以恒定速率无限期地“流入”,这将特别有益。
当然,当屏幕上出现如此多的项目时,您可能还得专注于渲染它本身。如果您的 ItemTemplate 很复杂,则 1000 个对象乘以 1000 个可视层/属性实例可能会破坏用户体验。您是否已将 ItemTemplate 简化到最低限度?
最后一件事:考虑使用虚拟化 StackPanel 作为 ItemsControl/ListBox 中的 ItemPanel。它可以大大减少内存占用和单个时间点绘制的项目数量。这不一定有助于增加引发的事件的数量或事件,但当您有复杂的项目模板时,它可能会有很大帮助!
编辑:您正在使用 ObservableCollection,所以我假设 WPF/Silverlight..如果这不正确,请更新问题
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)