WPF InitializeComponent 性能问题

8
我有一个WPF应用程序(.NET 4),它有一个主窗口,在该主窗口内显示许多较小的UserControls。用户执行的各种操作导致显示的UserControls被不同的其他控件替换,这些控件具有不同的数据。
然而,当切换这些控件时,我遇到了性能问题。加载控件时,WPF调度程序线程的CPU占用率达到100%。在旧机器上或者有大量控件时,这可能导致应用程序看起来锁定长达30秒!
分析表明,几乎所有的CPU时间都花费在调用各种UserControls的InitializeComponent方法上,没有一个控件比其他控件更糟糕,它们似乎都需要0.2到0.5秒(在我的开发机器上,它配备了快速处理器和良好的显卡)。
据我所知,InitializeComponent是WPF实际将编译后的xaml加载到内存中的地方。
我不知道该怎么办。我想在后台线程上预初始化一些东西,但所有的WPF控件必须在调度程序线程上创建和使用,因此我认为这是不可能的。
否则,看起来我唯一的选择就是删除所有的xaml?
非常感谢您的帮助。

1
不了解您的应用程序(具体细节+代码),我只能想象您可能有大量用户控件(+50)和/或非常重的数据绑定。因此,唯一的答案就是重新设计您的应用程序逻辑。您还必须了解的是,当涉及到大量控件/数据时,WPF绝对是垃圾,因为它没有经过充分优化(我猜这是一个太高级的框架)。也许尝试使用WinForms来开发您的应用程序(这会好一些),或者像Photoshop、AutoCAD那样使用本机c++/directx编写所有内容。 - Marko
我猜这些控件正在被加载,生成并可能被缓存。它确实提到了 PIX(一种 WPF 性能工具),你可能想试试。 - gbjbaanb
3个回答

4

重新审视这个问题——我们屏幕上有许多复杂的控件,但我们不能仅仅为了让WPF满意而将它们全部删除!

进一步的实验表明,使用自定义控件(基本上只是从Control派生出来的C#类,并在Generic.xaml主题文件中定义UI)似乎只会产生一次加载和解析XAML的开销。此后,每个控件只需应用预先存在的主题。

自定义控件比UserControls更难处理,但这确实在很大程度上帮助了我们的加载性能。


0
记录一下,我的窗口加载时间大约在1500~2000毫秒左右,问题出在图标上。
我使用了一个将SVG转换为XAML DrawingImage元素的工具,并且使用了一个包含每个使用的图标的绘图图像的大型资源字典的用户控件。
InitializeComponent非常慢,因为它必须解析包含所有图像矢量数据的大型XAML文件。
希望这能有所帮助。

0

InitializeComponent 方法需要一些时间,因为它需要将控件插入到视觉/逻辑树中,并确保所有绑定、主题、预期资源等都正确。

我的唯一建议是 - 是否可能从一开始就初始化所有潜在的控件,然后使用 Visibility 属性在需要时显示/隐藏它们?

您可以使用 Freezable 缓存一些 UI,但如果它们是用户控件,则最有可能希望用户与它们交互。


谢谢您的回答,但我们最初是将所有控件一次性加载,然后只显示我们需要的控件。然后,在首次显示窗体时出现了巨大的延迟(在较慢的机器上超过一分钟),这比当前行为更糟糕的用户体验 :-( - Orion Edwards

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