WPF:缓慢的模板实例化

本文关键字:实例化 缓慢 WPF | 更新日期: 2023-09-27 17:53:34

我有一个WPF应用程序,它很慢。

它是不是渲染。首先,渲染非常简单,其次,我用WPF性能工具包看了看,什么都没有。

在我自己的代码中是NOT。首先,单元测试工作得很快,其次,如果我用空白的datatemplate替换所有的datatemplate,一切都工作得很快。

到目前为止,看起来慢的部分是模板实例化。也就是说,当您启动应用程序并打开一些复杂的屏幕时,它将花费很多时间。我说的"a lot"是指"a lot"。有时可能长达3-5秒—例如,当有100行的数据网格时。但是当你转到另一个选项卡,然后再回到同一个屏幕时,它打开得很快(只要它的视图模型保持不变)。

这很烦人,不仅因为它很慢,还因为我对此无能为力。如果我可以控制慢速,我可以,也许,显示一些"打开,请等待"消息或其他…

此外,当我看到其他一些WPF应用程序(最值得注意的是ILSpy)时,它们似乎工作得相当快,尽管数据量很大。这让我觉得我可能做错了什么。但是我不知道从哪里开始。

任何想法?有什么经典错误吗?任何建议吗?

WPF:缓慢的模板实例化

我的经验来自WPF思维导图应用程序NovaMind

几个月前,我们完全重写了中间层来解决我们遇到的性能问题。简而言之,创建我们的用户控件似乎很慢。不幸的是,我没有找到一个很好的方法来分析性能,因为无论是WPF性能套件还是商业应用程序(如ANTS Profiler)都没有提供关于WPF过程这一部分的任何详细信息。(我当时问过这个问题)

我们通过试错来手动测试我们的应用程序,并删除了部分用户控件,以查看究竟是什么罪魁祸首。

最后,我们通过完全重写控件来解决性能问题。我们还大大降低了视觉树的复杂性。在重写之前,我们最常用的用户控件之一,当使用Snoop检查时,由61个不同的东西组成,现在只有3个。只要有可能,我们只根据需要向可视树中添加东西。(如您所知,在XAML中,即使将事物设置为collapse,也需要首先创建它们)。最后,我们被迫编写自己的富文本渲染控件,因为内置的RichtextBox非常慢,而且RichtextBox的可视化树非常复杂。

我不知道这是否适用于你的情况,但我建议你调查你的用户控制,看看他们是否复杂。也许你有可以修剪的地方。Low hanging fruits是那些很少可见的部分,或者可以用一种懒惰的方式创建。必要时可以在后台代码中创建这些部分,而不是在XAML中创建它们。这应该对你有很大帮助。

如果可能的话,虚拟化是您的朋友。不幸的是,我们不能这样做。

这听起来和我遇到的问题很相似。我在这里发布了修复:WPF UI自动化问题。只是为了搜索者的利益而发布,因为它需要很长时间才能解决。

下面的评论是关于链接的回答,这是那个帖子的关键:

我做了以下操作:

  1. 已下载的Hotfix - - http://archive.msdn.microsoft.com/KB978520(可能不需要)
  2. 下载修复程序- - http://archive.msdn.microsoft.com/KB2484841(绝对需要,即使你有Windows 7/.NET 4)
  3. 进一步改进了代码(验证导致对象过多)-为什么WPF样式在工具提示中显示验证错误对文本框有效,但对组合框无效?

可能只需要3号,但它起作用了。只是在这里发布,这样人们就不会失去我在内存分析器等方面失去的日子。

用户控件在你的数据模板,这不是完全坏主意,但如果你渴望性能,那么你应该考虑切换到更轻的控件。例如,让一个UserControl只承载一个TextBox是非常糟糕的主意,因为UserControl由ContentControl组成,ContentControl承载ContentPresenter, ContentPresenter承载TextBox,所以如果你注意到你的视觉树,它有三个新的UI元素层。减少视觉树肯定会提高性能。

最有可能的是,我建议创建自定义控件,它可能是一个全新的控件,几乎没有依赖属性,可以与你想要呈现的数据相关,你可以在generic.xaml中拥有自己的自定义模板。第二,您可以简单地从现有控件派生一个控件,并在generic.xaml中重新定义它的默认模板。

这种方法肯定会更好地工作,因为你将减少你的可视化树,从而减少可视化状态管理器的工作。

更改主题或模板将比更改承载内容的元素慢。并且让元素在它自己的泛型资源字典中拥有默认模板。

  • 尝试将所有资源向上移动只要他们愿意,最好是进入app.xaml
  • 检查您是否可以使用StaticResource不是动态的,而是静态的快多了
  • 如果可能,尝试使用依赖属性,特别是如果你可以同时拥有很多它们有很多属性。这将使wpf不必做一堆反射。

您提到您正在使用具有100行的DataGrid。您的性能问题的一个可能的罪魁祸首是您正在使用的数据网格没有进行虚拟化,因此您的可视化树是巨大的。

通常,WPF屏幕中较长的启动时间指向一个较大的可视树。

我不确定你是否使用数据模板每行,或一些第三方网格绑定列,或什么-但让我们说你有8列与控件。根据你的网格/验证等,这可能是一个20-60项的可视化树每行。如果您有一个组合框,那么下拉框中的每个项也可以按行创建。

要解决这个问题,只需要注意细节,并采取措施:

  1. 尽可能使用虚拟化控件。这意味着在列表控件中使用virtualizingstackpanel,并确保您的第三方控件也这样做(许多库存WPF控件现在默认这样做)
  2. 不要过度使用用户控件、复合控件等。增加深度会增加时间,在数据模板或其他重复区域添加额外的视觉树深度会增加时间。
  3. 如果所有这些都失败了,显示一个简单的屏幕,并通过代码添加控件来提高感知性能