在WPF中重复打开对话框时的性能问题

7

我有一个启动对话框按钮,它创建了一个窗口的视图模型并将其绑定到窗口上(它启用了UI虚拟化)。第一次点击启动对话框只需要1秒钟。但是,如果我非常频繁地或连续打开同一个对话框,下一次迭代中填充网格数据源就开始花费更多的时间。如果我暂停一下,然后再次打开窗口,那么大约只需要1或2秒钟。

for first time populating the item source it take only 1 second:
next time populating the item source it takes  2 second
next time populating the item source it takes  3 second
next time populating the item source it takes  6 second
next time populating the item source it takes  8 second

然而,如果我调用不建议使用的GC.Collect()方法,那么填充网格数据源始终需要大约1秒钟。但是调用
Gc.Collect()
Gc.WaitForPendingFinalizer()
Gc.Collect()

每次迭代都会花费我一些时间。

我知道调用 GC.Collect 不是一个好的选择。有人可以建议如何提高我的应用程序性能吗?

我更关注用户机器,因为我的机器配置非常好,而用户机器可能没有那么快。


1
为什么每次打开对话框都需要更长的时间?也许是因为您正在加载过多的数据。考虑使用分页(在网格和SQL查询中)使用分页 - Tim Schmelter
Tim,我也不明白。可能是我漏掉了什么,但不知道是什么。所以在寻找可能的错误。 - Yogesh
Tim的数据是相同的,它只加载了200行对象。如果数据确实很大,我会考虑使用数据虚拟化。但第一次加载相同的数据只需要1秒钟,而在5-7次迭代之后,它需要更多的时间。 - Yogesh
有趣的问题,我也很想知道原因。如果我创建一个简单的显示对话框应用程序,是否容易复现?此外,您是否在每个新对话框中检查内存消耗?只是猜测,减速是否由于磁盘分页造成的,可能是由于内存不足所致? - Peter
@Peter,请看我的评论。CharithJ所述的原因是最可能的原因。 - Yogesh
显示剩余4条评论
1个回答

3

没有查看代码很难确定具体问题。然而,通常出现这种情况有几个原因。

  1. 每次加载更多数据(可能是两倍?)。你已经指出每次只加载200条记录。但要确保逻辑正确,并在重新发布之前清除先前的数据。

  2. 确保取消订阅任何事件订阅。有时会触发以前网格实例的隐藏事件。您可以轻松检查它,方法是在事件处理程序上设置断点并检查它是否触发了多次。

  3. 查看您创建的每个Disposable实例,并检查是否适当地处置了它们。可能您没有处置可处置的实例,这可能是GC.Collect帮助的原因。

  4. 我不太确定虚拟化是否涉及在此处。执行相同的测试,但不使用虚拟化,以确保那不是原因。


谢谢CharithJ,我已经找到问题所在了,是因为我没有取消订阅事件,但我还是想知道为什么这个事件没有自动触发,因为我只是通过执行某些操作手动触发了它。所以它不应该对性能产生影响。现在,我更想知道存储如此多的事件处理程序是否会影响性能。我不明白这个问题。就内存而言,它们并没有占用太多的内存。即使它们占用更多,它们如何影响性能呢?你能给我一些提示吗? - Yogesh
不需要占用太多内存来引发内存问题。也许你正在处理大对象?请阅读 https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/。记得在对象超出范围之前处理所有可处理的对象。实现IDisposable接口并在Dispose方法中取消订阅任何事件。 - CharithJ
非常感谢分享这篇文章,这正是我在寻找的。 - Yogesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接