细数改善WPF应用程序性能的10大方法
WPF(Windows Presentation Foundation)應(yīng)用程序在沒有圖形加速設(shè)備的機(jī)器上運(yùn)行速度很慢是個(gè)公開的秘密,給用戶的感覺是它太吃資源了,WPF程序的性能和硬件確實(shí)有很大的關(guān)系,越高檔的機(jī)器性能越有優(yōu)勢(shì)。?
程序性能改善不是一蹴而就的,好的設(shè)計(jì)可以消除影響性能的問題,例如,在運(yùn)行時(shí)構(gòu)造對(duì)象就會(huì)對(duì)程序的性能造成影響。雖然WPF通過增強(qiáng)的導(dǎo)航等功能提供了更豐富的用戶界面,但你應(yīng)該考慮你的用戶是否的確需要富圖形界面,盡管WPF有這樣那樣的問題,但在UI設(shè)計(jì),特別是自定義風(fēng)格和控件模板方面,的確給開發(fā)人員提供了不少靈活性。
圖 1 WPF架構(gòu),藍(lán)色是Windows組件,褐色是WPF組件
渲染W(wǎng)PF程序的主要因素是它包含的像素量,WPF使用微軟的DirectX在程序運(yùn)行的硬件上進(jìn)行渲染,因此,如果你的機(jī)器有獨(dú)立顯卡,運(yùn)行WPF程序會(huì)更流暢。除了提高硬件配置外,我們來看看10個(gè)提高WPF程序性能的軟方法。
1、降低Bitmapscalingmode,加速圖像渲染
當(dāng)你的WPF程序中包含有動(dòng)畫時(shí),你可以使用RenderOptions對(duì)象的BitmapScalingMode屬性降低資源消耗,需要將BitMapScalingMode屬性的值設(shè)為L(zhǎng)owQuality,這樣就會(huì)使用加速算法處理圖像,而不是默認(rèn)的高質(zhì)量圖像重采樣算法。下面的代碼片段顯示了最基本的實(shí)現(xiàn)方法:
RenderOptions.SetBitmapScalingMode(imageObject,BitmapScalingMode.LowQuality);?
2、在正確的地方使用正確的元素
我們需要在正確的地方使用正確的元素,當(dāng)你生成樹時(shí)應(yīng)避免使用UIElements作為子或嵌套控件,最好的例子是FlowDocument,我們經(jīng)常在FlowDocument中使用TextBlock元素。
<FlowDocument> ????<Paragraph> ??????<TextBlock>some text</TextBlock> ????</Paragraph> ??</FlowDocument>?
除了上面這樣寫外,我們還可以象下面這樣重寫XAML內(nèi)容,Run元素不是UIElement,渲染時(shí)系統(tǒng)開銷更小。
<FlowDocument>??<Paragraph>????<Run>some text</Run>??</Paragraph></FlowDocument>?
類似的例子是使用Label控件的Content屬性,如果在其生命周期內(nèi)內(nèi)容不止更新一次,并且是個(gè)字符串,這個(gè)數(shù)據(jù)綁定過程可能會(huì)阻礙程序的性能,由于內(nèi)容是一個(gè)字符串,在數(shù)據(jù)綁定期間它會(huì)被丟棄,并重新創(chuàng)建。在這種情況下使用TextBlock將數(shù)據(jù)綁定到Text屬性更有效。
在可視化樹中出現(xiàn)不必要的元素也會(huì)降低WPF程序的速度,你最好結(jié)合布局優(yōu)化默認(rèn)的控件模板。
3、增加靜態(tài)資源的使用
靜態(tài)資源是預(yù)定義的資源,可以連接到XAML屬性,它類似于編譯時(shí)綁定,不會(huì)影響性能,另一方面,動(dòng)態(tài)資源涉及到運(yùn)行時(shí)查找和對(duì)象的構(gòu)建,從而會(huì)影響到性能。但也需要注意,靜態(tài)資源需要在編譯時(shí)展示。
靜態(tài)資源的引用可以參考下面的方法:
<Button ????????Template="{StaticResource RoundButtonWithThickEdge}" ???????? x:Name="button1" Content="Button 1"> ??</Button>?
下面的代碼片段顯示了靜態(tài)資源RoundButtonWithThickEdge的定義:
<ControlTemplate ?????? x:Key="RoundButtonWithThickEdge" ?????? TargetType="{x:Type Button}"> ?????? <Grid> ???????? <Ellipse Fill="{TemplateBinding Background}" ?????????? Stroke="{x:Null}" ?????????? HorizontalAlignment="Stretch" x:Name="ellipse"/> ???????????? <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> ???????????????? <Ellipse Stroke="{x:Null}" Margin="2,3,4,5"> ?????????????????? <Ellipse.Fill> ???????????????????? <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> ?????????????????? <GradientStop Color="#FFFBFAFA" Offset="0"/> ??????????????????<GradientStop Color="#1DFFFFFF" Offset="1"/> ???????????? </LinearGradientBrush> ?????????? </Ellipse.Fill> ???????? </Ellipse> ?????? </Grid> ???? </ControlTemplate>?
4、當(dāng)你想顯示大型數(shù)據(jù)時(shí),使用UI虛擬化的控件
想象一下一個(gè)組合框綁定大量行時(shí)的樣子,它會(huì)讓組合框中項(xiàng)目的展現(xiàn)變得非常慢,這是因?yàn)樵谶@種情況下,程序需要計(jì)算每個(gè)項(xiàng)目的具體顯示位置,使用WPF時(shí),你可以延遲這個(gè)行為,這就叫做UI虛擬化,它只會(huì)在其可見范圍內(nèi)生產(chǎn)項(xiàng)目顯示需要的容器。
要實(shí)現(xiàn)這種效果,你需要將相應(yīng)控件的IsVirtualizing屬性設(shè)為True,例如,Listbox經(jīng)常用來綁定大型數(shù)據(jù)集,它是UI虛擬化的重要候選者,其它適宜UI虛擬化的控件包括Combobox,ListView和TreeView。
5、使用延遲滾動(dòng)增強(qiáng)用戶體驗(yàn)
如果你還記得可滾動(dòng)的DataGrid或ListBox,它們往往會(huì)降低整個(gè)應(yīng)用程序的性能,因?yàn)樵跐L動(dòng)時(shí)會(huì)強(qiáng)制連續(xù)更新,這是默認(rèn)的行為,在這種情況下,我們可以使用控件的延遲滾動(dòng)(Deferred Scrolling)屬性增強(qiáng)用戶體驗(yàn)。你需要做的僅僅是將IsDeferredScrollingEnabled附加屬性設(shè)為True。
6、使用字體緩存服務(wù)提高啟動(dòng)時(shí)間
WPF應(yīng)用程序之間可以共享字體數(shù)據(jù),它是通過一個(gè)叫做PresentationFontCache Service的Windows服務(wù)實(shí)現(xiàn)的,它會(huì)隨Windows自動(dòng)啟動(dòng)。
你可以在控制面板的“服務(wù)”中找到這個(gè)服務(wù)(或在“運(yùn)行”框中輸入Services.msc),確保這個(gè)服務(wù)已經(jīng)啟動(dòng)。
7、使用卸載事件卸載不必要的動(dòng)畫
動(dòng)畫肯定會(huì)占用一定的資源,如果處置方式不當(dāng),將會(huì)消耗更多的資源,如果你認(rèn)為它們無用時(shí),你應(yīng)該考慮如何處理他們,如果不這樣做,就要等到可愛的垃圾回收器先生來回收資源。
例如,假設(shè)要?jiǎng)h除一個(gè)StoryBorad,在Unload事件中使用StoryBorad的Remove方法,下面的例子來自MSDN。
<EventTrigger RoutedEvent="Page.Unloaded"> ??????????<EventTrigger.Actions> ????????????<RemoveStoryboard BeginStoryboardName="myBeginStoryboard"/> ??????????</EventTrigger.Actions> ??</EventTrigger>?
8、使用容器回收提高性能
你可以通過回收?qǐng)?zhí)行虛擬化的容器來提高性能,下面的代碼片段將ViruatlizationMode設(shè)為Recycling,它讓你可以獲得更好的性能。當(dāng)用戶滾動(dòng)或抵達(dá)另一個(gè)項(xiàng)目時(shí),它強(qiáng)制重復(fù)使用容器對(duì)象。
settingVirtualizingStackPanel.VirtualizationMode="Recycling"?
9、預(yù)測(cè)圖像繪制能力
使用RenderCapability.Tier屬性確定機(jī)器是支持硬件加速,還是部分硬件加速,疑惑沒有硬件加速,下面的代碼顯示了你要如何檢查Tier。
int displayTier = (System.Windows.Media.RenderCapability.Tier >16) ?? ??if (displayTier ==0) ??{ ???? //no hardware acceleration ??} ??elseif (displayTier ==1) ??{ ???? //partial hardware acceleration ??} ??else ??{ ???? //supports hardware acceleration ??}?
確定了之后,你就可以有選擇性地選擇那些在用戶硬件上工作得很好的功能
10、使用WPF分析工具分析WPF程序
分析WPF程序是理解其行為很重要的一步,市場(chǎng)上有大量現(xiàn)成的WPF程序分析工具,如Snoop,WPFPerf,Perforator和Visual Profiler,其中Perforator和Visual Profiler是WPF Performance Suite的一部分,要了解這些工具的用法,請(qǐng)去它們的項(xiàng)目主頁。
轉(zhuǎn)載于:https://www.cnblogs.com/happyyftk/p/3328160.html
總結(jié)
以上是生活随笔為你收集整理的细数改善WPF应用程序性能的10大方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 添加错误debug信息
- 下一篇: WPF的转换器中使用Brush应注意问题