您当前的位置: 首页 >  性能优化

君子居易

暂无认证

  • 0浏览

    0关注

    210博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

避坑OutOfMemory - WPF程序性能优化二

君子居易 发布时间:2021-03-17 11:01:13 ,浏览量:0

 

Point1:及时释放MediaElement

MediaElement调用的系统Windows Media Player.  WMP播放不出来的视频,在WPF程序里也会播不出来。 事实上MediaPlayer挺费内存和GPU的, UserControl.Unloaded中一定要及时释放播放器,否则最常见的问题,视频不显示了,但是视频声音还在。

Tips:

有时候明明是常见的.mp4.  .wmv视频文件,其他播放器能正常播放,但是在Windows Media Player中无法播放,WPF程序里也没法播放,崩着急, 检查下视频编码。  比如.mp4文件的编码就有:Divx;Xvid; H264; H265。  wmv编码有:WMV1,WMV2,WMV3, WMV9。 移动端以及浏览器端支持最好的视频格式为.H264编码、 音频编码.AAC的mp4文件。若WPF中无法播放mp4. wmv或其他格式视频,可以尝试对视频进行格式转换、变化下编码。

 

Point2:尽量用DispatcherTimer替代CompositionTarget.Rendering

CompositionTarget.Rendering在使用时,若GPU、CPU耗费较高,鼠标滑动一下,都能感觉出程序节奏的明显不稳定。

比如在做内容滚动时,推荐使用DispatchTimer。

 

Point3:大量UI对象需要创建或者加载

数量级超大时,用虚拟化的方式实现,例ListBox的虚拟化技术,最常见的就是Office中的Word,上百页的文档滚动时,不采用虚拟化技术的话,绝对卡死。 

数量级还凑合的时候,可以适当设置条件,例:200张小图片。  窗口界面就那么大,能显示的内容有限, 界面暂时不呈现的,先以*.children.remove(*)方式移除。 例我开源项目 https://github.com/DuelWithSelf/WPFEffects  中的:Carousel3D。  一定角度范围内的才 使用*.Children.Add(*)。 即保证当前窗口需要呈现的内容添加到界面就行,一旦不显示了,立即移除。 减少UI线程的渲染耗能。我的Demo效果如下:

这个Demo我后面又优化了,后续逐步更新至Github。  不在窗口前端呈现时,连Image所在的UserControl对象都不需要创建。页面打开时,相当于只创建了5、6个元素块添加到界面, 滑动到哪,创建到哪。   否则一下创建出所有的对象添加至界面,性能不好时程序能卡半天。 

数量级较大时,延时创建和加载非常有必要。最简单的测试: private List ImgItems = new List();

private void DoLoadUIElement() {     for (int i = 0; i < 100; i++)         ImgItems.Add("FileName" + i);

    Task.Run(async () =>     {         for (int i = 0; i < ImgItems.Count; i++)         {             if (ImgItems != null)             {                 await Task.Delay(100);                 await this.Dispatcher.BeginInvoke((Action)(() =>                 {                     DoCreateUIElement(i);                 }));             }         }     }); }

private void DoCreateUIElement(int nIndex) {     string str = this.ImgItems[nIndex];     Console.WriteLine("Create Time(Millisecond):" + DateTime.Now.Millisecond + "  Create Element:" + str ); }

可以拷贝上述代码,试一下。输出如下,界面Loaded时,有效的将要一次性创建显示的内容通过延时处理分散下, 否则CPU、GPU爆发力不够的话,界面卡是一定得。

Point5: WPF中图片加载

WPF应用打包后,你会发现,几万行代码打包出来也就几M的大小,但是程序中若嵌入了图片, 那最终的exe肯定不会太小。适当的图片压缩很有必要,图片质量越高,对显卡性能要求也就越高。 一般的电脑分辨率也就1920*1080. 不做专业看图模块的话, 图片资源的分辨率高于这个比例,其实是没多少必要的。 大于300M以上的高质量图片,WPF程序不做适当处理、释放内容方面又没做到位的话,加载几张程序就会报OutOfMemery。 这时候图片切分很有必要。  WPF程序加载20张15M的图片,程序不会死、 但是一次性或多次加载300M的图片,嘿嘿,感兴趣的可以试试。后续单独发文讲述我是如何在WPF中切段加载超过几万像素、几百M大图的。

推荐加载方式:图片加载时,先设置DecodePixelWidth和 DecodePixelHeight。 比如Image的高度1920*1080。 那就先设置成192* 108.  让画面先快速加载出来, 然后再用延时的方式,加载高质量原图。 这样新界面打开时,速度会快很多,用户体验也会更佳,否则跳转界面老卡顿,很恼火的。 BitmapImage bitmap = new BitmapImage(); bitmap.DecodePixelWidth = 192; bitmap.DecodePixelHeight = 108; bitmap.UriSource = new Uri(""); Image.Source = bitmap;  

关注
打赏
1660814979
查看更多评论
立即登录/注册

微信扫码登录

0.0362s