跳至正文
首页 » 博客 » 15 WPF Performance Tips

15 WPF Performance Tips

您是WPF开发人员吗?您的WPF应用程序是否存在性能较差的区域,或者运行速度不如您希望的那样快?如果是这样,我有15帮助您识别和提高WPF应用程序性能的提示。

虽然WPF已经有十多年的历史了,而且多年来已经有了很大的改进,但仍然有几个可能遭受性能不佳的区域。表现不佳的原因包括诸如编码实践、断开的绑定、复杂的布局、缺乏UI虚拟化等等。幸运的是,通过对WPF平台的一点规划和扎实的理解,您可以让您的WPF应用程序跳入warp speed和跳跃以毫秒为单位穿越宇宙。

我已经整理这些15技巧帮助您提高性能的WPF应用程序。

1.简化你的可视化树

性能问题的一个常见来源是深度和复杂的布局。使XAML标记尽可能简单和浅。在屏幕上绘制UI元素时,会为每个元素调用两次 “布局传递” (测量传递和排列传递)。的布局传递是一个数学密集型过程-儿童元素,所需的计算次数越多

2.虚拟化您的ItemsControls

如前所述,复杂而深入的可视化树会导致更大的内存占用和更慢的性能。ItemsControls通常会增加深层可视化树的性能问题,因为它们不是虚拟化的。这意味着它们会不断地为控件中的每个项创建和销毁。相反,使用VirtualizingStackPanel作为项宿主,并使用VirtualizingStackPanel.IsVirtualizing并将VirtualizationMode设置为Recycling,以便重用项容器,而不是每次都创建新的项容器。

3.偏向静态资源而不是动态资源

StaticResources通过查找对已定义资源的引用为任何XAML属性特性提供值。该资源的查找行为与编译时查找相同。DynamicResources将创建临时表达式并推迟对资源的查找,直到需要请求的资源值。该资源的查找行为与运行时查找相同,这会影响性能。始终尽可能使用StaticResource。

4.画笔上的不透明度而不是元素

如果使用画笔设置元素的填充或描边,最好在画笔上设置不透明度,而不是设置元素的Opacity属性。修改元素的Opacity属性时,可能会导致WPF创建临时曲面,从而导致性能命中。

5.避免使用Run设置文本属性

避免在TextBlock中使用运行,因为这会导致更高性能的密集型操作。如果使用运行来设置文本属性,请直接在TextBlock上设置这些属性。

6.偏爱流几何而不是路径几何

StreamGeometry对象是PathGeometry的一个非常轻量级的替代对象。StreamGeometry针对处理许多PathGeometry对象进行了优化。与使用许多PathGeometry对象相比,它占用的内存更少,并且性能更好。

7.使用缩小的图像尺寸

如果您的应用需要显示较小的缩略图,请考虑创建图像的缩小版本。默认情况下,WPF会将图像加载并解码为其完整大小。如果要加载完整图像并将其缩小到控件 (如ItemsControl) 中的缩略图大小,这可能是许多性能问题的根源。如果可能,将所有图像合并为单个图像,例如由多个图像组成的胶片带。

8.降低BitMapScalingMode

默认情况下,WPF使用高质量图像重新采样算法,该算法有时会消耗系统资源,从而导致帧速率降低并导致动画停顿。相反,将BitMapScalingMode设置为LowQuality以从 “质量优化” 算法切换到 “速度优化” 算法。

9.使用和冻结Freezables

Freezable是一种特殊类型的对象,具有两种状态: 解冻和冻结。冻结对象 (如笔刷或几何体) 时,无法再对其进行修改。尽可能冻结对象可以提高应用程序的性能并减少其内存消耗。

10.修复您的绑定错误

绑定错误是WPF应用程序中最常见的性能问题类型。每次发生绑定错误时,您的应用程序都会受到影响,并尝试解决绑定并将错误写入跟踪日志。你可以想象,更多的绑定错误,你有更大的性能打击你的应用程序将采取。花点时间查找并修复所有绑定错误。在DataTemplates中使用RelativeSource绑定是绑定错误的主要原因,因为在DataTempate完成其初始化之前,绑定通常无法正确解析。不惜一切代价避免使用RelativeSource.FindAncestor。而是定义附加属性并使用属性继承将值向下推送到可视化树中,而不是查找可视化树。

11.避免数据绑定到Label.Content属性

如果您使用标签将数据绑定到字符串属性,这将导致性能不佳。这是因为每次更新字符串源时,都会丢弃旧的字符串对象,并创建一个新的字符串。如果标签的内容是简单文本,则将其替换为TextBlock并绑定到text属性。

12。将ItemsControls绑定到IList而不是IEnumerable

将ItemsControl数据绑定到IEnumerable时,WPF将创建IList<T> 类型的包装,这会对创建第二个对象的性能产生负面影响。而是将ItemsControl直接绑定到IList,以避免包装对象的开销。

13.使用NeutralResourcesLanguage属性

使用NeutralResourcesLanguageAttribute告诉ResourceManager什么是非特定区域性,并避免不成功的附属程序集查找。

14.在单独的线程上加载数据

性能问题、UI冻结和应用程序停止响应的一个非常常见的来源是如何加载数据。确保您在单独的线程上异步加载数据,以便不重载UI线程。在UI线程上加载数据将导致非常差的性能和整体糟糕的最终用户体验。多线程应该是每个WPF开发人员在其应用程序中使用的东西。

15。谨防内存泄漏

在大多数WPF应用程序中,内存泄漏是性能问题的首要原因。它们很容易拥有,但很难找到。例如,使用DependencyPropertyDescriptor.AddValueChanged可能会导致WPF框架采用对事件源的强引用,直到您手动调用DependencyPropertyDescriptor.RemoveValueChanged时才会移除该事件源。如果您的视图或行为依赖于从对象或ViewModel (如INotifyPropertyChanged) 引发的事件,请弱订阅它们或确保您手动取消订阅。此外,如果你绑定到一个ViewModel不实现INotifyPropertyChanged属性,机会是你有一个内存泄漏。

最后,奖金提示。有时,当您遇到性能问题时,很难确定到底是什么导致了问题。我建议使用应用程序性能分析器来帮助识别这些性能瓶颈在您的代码库中发生的位置。有很多可用的profiler选项。有些是付费的,有些是免费的。我个人使用最多的是诊断工具直接内置到Visual Studio 2019中。

一定要和我交往Twitter,订阅我的YouTube频道收到新视频内容的通知,并关注我抽搐看我直播。如果您正在使用WPF的终极UI,请务必通过我们的社区论坛您可以在其中与Infragistics工程师和其他客户进行交互。</p