WPF:慢速模板实例化

时间:2011-04-26 12:35:30

标签: c# wpf performance templates

我有一个WPF应用程序,而且速度很慢。

渲染。首先,渲染非常简单,其次,我使用WPF Performance Toolkit查看它 - 没有。

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

到目前为止,看起来缓慢的部分是模板实例化。也就是说,当你启动应用程序并打开一些复杂的屏幕时,它需要很多的时间。并且通过“很多”我的意思是“很多”。有时可能长达3-5秒 - 例如,当有一个包含100行的数据网格时。但是当你转到另一个标签,然后回到同一个屏幕时,它会快速打开(只要它的视图模型保持不变)。

这非常烦人,不仅因为它很慢,而且因为我无能为力。如果我对缓慢有一些控制,我可能会显示一些“打开,请等待”的消息或其他...

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

有什么想法吗?任何经典错误?有什么提示吗?

5 个答案:

答案 0 :(得分:5)

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

几个月前,我们完全重写了我们的中间层,以解决我们遇到的性能问题。简而言之,创建用户控件似乎是放慢速度的方法。遗憾的是,由于WPF Performance Suite和ANTS Profiler等商业应用程序都没有为WPF流程的这一部分提供任何详细信息,因此无法找到一种很好的方式来分析性能。 (当时我问过this question

我们通过反复试验手动测试我们的应用程序,并删除了部分用户控件,以确定究竟是什么罪魁祸首。

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

我不知道这是否适用于您的情况,但我建议您调查用户控件并查看它们是否复杂。也许你有可以修剪的东西。 低悬的水果将是很少可见的部分,或者可以以懒惰的方式创建。您可以在必要时从代码后面创建这些部分,而不是在XAML中使用它们。这应该会对你有所帮助。

如果可能的话,虚拟化就是你的朋友。在我们的案例中,我们不幸地不能这样做。

答案 1 :(得分:2)

这听起来类似于我遇到的问题。我在这里发布了修复程序:WPF UI Automation issue。只是为搜索者的利益发布,因为需要很长时间才能解决。

关于仅链接回答的评论,以下是该帖子的关键:

我做了以下事情:

  1. 已下载的修补程序 - http://archive.msdn.microsoft.com/KB978520(可能不是必需的)
  2. 已下载的修补程序 - - http://archive.msdn.microsoft.com/KB2484841(即使您拥有Windows 7 / .NET 4也一​​定要求)
  3. 进一步改进了代码(验证导致了过多的对象) - Why does WPF Style to show validation errors in ToolTip work for a TextBox but fails for a ComboBox?
  4. 可能只需要3号,但它有效。只是发布在这里,所以人们不会失去我在内存分析器等中丢失的日子。

答案 2 :(得分:1)

数据模板中的用户控制并不是一个坏主意,但如果你渴望性能,那么你应该考虑切换到更轻的控制。例如,让UserControl只托管TextBox是个坏主意,因为UserControl由ContentControl组成,ContentControl主机ContentPresenter和ContentPresenter将托管TextBox,所以如果你注意到你的Visual Tree,它有三个新的UI元素层。减少Visual Tree肯定会提高性能。

我很可能会建议创建自定义控件,它可能是一个完全新的控件,具有很少的依赖属性,可以与您想要呈现的数据相关,并且您可以在generic.xaml中拥有自己的自定义模板。其次,您只需从现有控件派生控件,并在generic.xaml中重新定义其默认模板。

这种方法肯定会更好,因为您将减少Visual Tree,从而减少Visual State Manager的工作。

更改主题或模板的速度会慢于更改承载内容的元素。让元素在其自己的通用资源字典中具有默认模板。

答案 3 :(得分:1)

  • 尝试将所有资源向上移动 他们会去,最好是 App.xaml中
  • 检查您是否可以使用StaticResource 而不是动态的,静态的 很快
  • 如果可能,请尝试使用dependdency 虚拟机中的属性,尤其是 你有很多他们或者如果 他们有很多属性。这将使wpf不必进行一堆反思。

答案 4 :(得分:1)

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

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

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

要解决此问题,只需观察细节,并采取措施:

  1. 尽可能使用虚拟化控件。这意味着在列表控件中使用virtualizingstackpanel,并确保您的第三方控件也可以执行(默认情况下,许多股票WPF控件都可以使用)
  2. 不要过度使用UserControls,复合控件等。添加深度会增加时间,并且在数据模板或其他重复区域中添加额外的可视树深度会加快。
  3. 如果所有其他方法都失败了,请显示一个简单的屏幕并通过代码添加控件以提高感知效果