UI 线程在加载和更新 RadGridView 对象时停止
下午,
我目前正在分析一个相当大的 C# WPF 应用程序,试图消除一些性能问题。其中一种涉及切换到特定(相当大)的 UserControl 时发生的 5-8 秒停顿。我已将范围缩小到此 UserControl 中包含的 RadGridView,该控件需要很长时间才能加载和更新自身,从而导致 UI 线程停顿并使整个应用程序无响应。显然,如果可能的话,我们希望消除这种停顿。
我尝试去掉网格上的任何自定义样式和 DataTriggers,但是虽然这总体上减少了 UI 线程的负载,但停顿仍然存在,似乎没有减少。通过 ANTS Profiler,似乎主要归咎于网格的测量和布局,以及 XAML 模板的一些加载。由于没有网格行,用户控件的加载速度明显加快,并且似乎仅添加少量行就足以导致这种停顿。网格为行和列启用了虚拟化,但这似乎没有帮助。检查后,调用图非常深,似乎是引发更新通知、更新布局、加载 XAML 以及最重要的是测量子 FrameworkElement 的调用才是罪魁祸首。
对于几个潜在的解决方案,我正在考虑将 UserControl 保留在内存中但隐藏以减少切换到它的成本,或者在 UserControl 加载后,可能会增量地填充网格。前者可能需要做很多工作,因为控件订阅了许多事物,需要根据需要连接、断开和重新连接。后者可能还涉及相当多的工作,但可能是一个更好的解决方案,因为这样至少我们可以尝试自己减轻停顿,或者至少在发生停顿时警告用户。
如果问题仍然存在,我们可能会要求 Telerik 看一下,但我想我应该先在这里问,以防有人以前遇到过这样的问题(甚至不一定是 RadGridView)并找到了解决方案一些描述。
干杯。
Afternoon all,
I'm currently profiling a rather large C# WPF app, trying to eliminate a few performance issues. One involves a 5-8 second stall that occurs when switching to a particular (rather large) UserControl. I've narrowed this down to a RadGridView contained in this UserControl that's taking a long time to load and update itself, stalling the UI thread and making the entire application unresponsive. Obviously, we'd like to eliminate this stall if possible.
I have tried stripping away any custom styles and DataTriggers on the grid, but while this acted to reduce load on the UI thread in general, the stall still remained, seemingly undiminished. Through ANTS Profiler, it seems that the measuring and layout of the grid is mostly to blame, along with some loading of XAML templates. With no grid rows, the UserControls loads significantly faster, and it seems that adding just a small number of rows is enough to bring about this stall. The grid has virtualization enabled for rows and columns, but this doesn't seem to help. The call graph is tremendously deep when examined, and it seems to be calls that raise update notifications, update layout, load XAML and, above all, measure child FrameworkElements that are to blame.
For a couple of potential solutions, I'm thinking about keeping the UserControl in memory but hidden to reduce the costs of switching to it, or populating the grid, perhaps incrementally, well after the UserControl has loaded. There might be a lot of work with the former, as the control subscribes to a number of things, which would need to be connected to, disconnected from and reconnected to as appropriate. The latter might also involve a fair bit of work, but might be a better solution, because then at least we could try to mitigate the stalling ourselves, or at least warn the user when it was occurring.
If the problem persists, we're likely to ask Telerik to have a look at it, but I thought I'd ask here first in case anyone has encoutered such an issue before (not necessarily with RadGridView, even) and found a solution of some description.
Cheers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是您需要一个正确实现 ICollectionChanged 的集合。
将所有记录添加到源集合后尝试此操作(每次添加后不应引发任何 CollectionChanged 事件),它有效:
注意我们传递的是
IList
,而不是TValue< /代码>。当它看到一个列表时,它会在处理之前将它们全部添加。 startingValue 通常是开始添加项目之前列表的 .Count。
步骤:
RadGridView 的一个奇怪行为是,如果您以这种方式添加一百万条记录,速度会很快,但所有新行都将为空白,您可以看到 RadGridView 慢慢地用来自的数据填充它们最上面的新项目下来。我的解决方案是绑定 QueryableCollection 并将其 PageSize 设置得足够小,这样用户就看不到这一点。
The problem is you need a collection that implements ICollectionChanged properly.
Try this after adding all records to your source collection (one which should NOT raise any CollectionChanged events after each add), it works:
Notice we're passing
IList<TValue>
, NOTTValue
. When it sees a list, it adds them ALL before processing. The startingValue is usually the .Count of the list before you started adding items.Steps:
QueryableCollectionView
which uses this list as its SourceCollection. I don't know if you can bind against this list directly.One strange behavior with RadGridView is that if you add say, a million records this way, it WILL be quick, but all the new rows will be blank, and you can watch RadGridView slowly populate them with data from the topmost new item down. My solution to this is to bind against QueryableCollection and set its PageSize sufficiently small so the users don't see this.