WPF 2019的性能提示

您是WPF开发人员吗?您的WPF应用程序是否存在性能低下的区域,或者运行得不尽如人意?如果是这样,我有15条提示可帮助您确定和提高WPF应用程序的性能。

尽管WPF已有十多年的历史,并且在过去几年中已经得到了很大的改进,但仍有几个领域可能会出现性能不佳的情况。表现不佳的原因包括不良的编码习惯,绑定断开,布局复杂,缺少UI虚拟化等等。幸运的是,只需进行一些计划并对WPF平台有扎实的了解,您就可以让WPF应用程序以惊人的速度跃升,并以毫秒为单位跨越整个宇宙。

我整理了这15条提示,以帮助您提高WPF应用程序的性能。

1.简化视觉树

性能问题的常见根源是深度和复杂的布局。使您的XAML标记替换简单和浅。当在屏幕上放置UI元素时,每个元素都会触发“布局遍历”(布局遍历和布置遍历) 。布局遍历是一个数学密集型过程-元素中的子代数越多,所需的计算数就越多。

2.虚拟化ItemsControls

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

3.偏爱StaticResources而不是DynamicResources

StaticResources通过查找对已定义资源的引用来为任何XAML属性属性提供值。该资源的查找行为与编译时查找相同。DynamicResources 将创建一个临时表达式并添加对资源的查找,直到需要所请求的资源值为止。该资源的查找行为与运行时查找相同,这会对性能造成影响。始终正确使用StaticResource。

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

如果使用“画笔”设置元素的“填充”或“描边”,则最好在“画笔”上设置“不对齐”,而不是设置元素的“不透明度”属性。修改元素的“不透明度”属性时,它可能导致WPF创建临时曲面,从而导致性能下降。

5.避免使用运行来设置文本属性

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

6.偏爱StreamGeometries而不是PathGeometries

StreamGeometry 经过优化,可以处理许多PathGeometry对象。与使用许多PathGeometry对象,它消耗了很多内存,并且性能更好。

7.使用缩小的图像尺寸

如果您的应用程序需要显示较小的尺寸,请考虑创建缩小尺寸的图像。替换情况下,WPF将加载并解码图像到其完整尺寸。如果要加载完整的图像尺寸为其缩小为ItemControl等控件中的尺寸大小,这可能是许多性能问题的根源。如果可能,将所有图像组合成一个图像,例如由多个图像组成的胶片。

8.降低BitMapScalingMode

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

9.使用和冻结

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

10.修正您的装订错误

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

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

如果使用标签将数据绑定到String属性,这将导致性能下降。这是因为每次更新String源时,都会丢弃旧的字符串对象,并创建一个新的String。如果Label的内容是简单文本,则将其替换为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),请进行进行弱订阅或确保您手动取消订阅。INotifyPropertyChanged的ViewModel中的属性,则很可能发生内存泄漏。

发布了18 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_28368039/article/details/105443644
WPF