1. 程式人生 > >WPF程序性能

WPF程序性能

sdk static 超鏈接 命名 ntp scroll dsc stat ebr

WPF程序性能由很多因素造成,以下是簡單地總結:

元素:

1、 減少需要顯示的元素數量:去除不需要或者冗余的XAML元素代碼. 通過移出不必要的元素,合並layout panels,簡化templates來減少可視化樹的層次。這可以保證第內存使用,而改變渲染性能。

2、 UI虛擬化:只顯示當前需要顯示的元素.

3、 不要把不要顯示的自定義控件隱藏在主界面中:雖然它們不會顯示出來,但是程序啟動時還是會去計算自定義控件所需的空間和位置.

4、 VirtualizingStackPanel對Item類型控件重寫時,使用VirtualizingStackPanel作為ItemPanel,這樣列表資源可以只渲染當前需要的內容。不過如果設置CanContextScrol="True"會阻止虛擬化,另外使用VirtualizingStackPanel時,可以設置VirtualizingStackPanel.VirtualizationMode="Recycling", 這樣已經顯示過的列表不會被重復創建和釋放掉。

5、 凍結可以凍結的控件:通過在代碼中調用Freeze()或者在Xmal中設定PresentationOptions:Freeze="true"來凍結可以凍結的控件。由於這樣系統不必監聽該控件的變化,所以可以帶來性能的提升.

6、 盡可能使用StreamGeometries 代替PathGeometries:因為它可以一低內存占用,更高效.

7、 盡量多使用Canvas等簡單的布局元素:少使用Grid或者StackPanel等復雜的,越復雜性能開銷越大

8、 盡量不要使用ScrollBarVisibility=Auto

9、 如果需要修改元素的Opacity屬性,最後修改一個Brush的屬性,然後用這個Brush來填充元素。因為直接修改元素的Opacity會迫使系統創建一個臨時的Surface

10、 使用延遲滾動增強用戶體驗:如果你還記得可滾動的DataGrid或ListBox,它們往往會降低整個應用程序的性能,因為在滾動時會強制連續更新,這是默認的行為,在這種情況下,我們可以使用控件的延遲滾動(Deferred Scrolling)屬性增強用戶體驗。你需要做的僅僅是將IsDeferredScrollingEnabled附加屬性設為True

11、 使用容器回收提高性能: 你可以通過回收執行虛擬化的容器來提高性能,下面的代碼片段將ViruatlizationMode設為Recycling,它讓你可以獲得更好的性能。當用戶滾動或抵達另一個項目時,它強制重復使用容器對象。

線程:

1、 耗時操作放在放在非UI線程上處理,保持UI的順暢:處理完成後如果需要在UI上展示,調用Dispatcher.BeginInoke()方法

綁定:

1、 Mode關於Data Binding,根據實際情況對Binding指定不同的Mode,性能比較:OneTime>OneWay>TwoWay。

2、 修正系統中Binding錯誤:在Visual Studio的輸出日誌中查找System.Windows.Data Error。

3、 在使用數據綁定的過程中,如果綁定的數據源是一個CLR對象,屬性也是一個CLR屬性,那麽在綁定的時候對象CLR對象所實現的機制不同,綁定的效率也不同。

4、 訪問CLR對象和CLR屬性的效率會比訪問DependencyObject/DependencyProperty高。註意這裏指的是訪問,不要和前面的綁定混淆了。但是,把屬性註冊為DependencyProperty會有很多的優點:比如繼承、數據綁定和Style。

5、 數據源是一個CLR對象,屬性也是一個CLR屬性。對象通過TypeDescriptor/PropertyChanged模式實現通知功能。此時綁定引擎用TypeDescriptor來反射源對象。效率最低。

6、 數據源是一個CLR對象,屬性也是一個CLR屬性。對象通過INotifyPropertyChanged實現通知功能。此時綁定引擎直接反射源對象。效率稍微提高。

7、 數據源是一個DependencyObject,而且屬性是一個DependencyProperty。此時不需要反射,直接綁定。效率最高。

8、 當一個CLR對象很大時,比如有1000個屬性時,盡量把這個對象分解成很多很小的CLR對象。比如分成1000個只有一個屬性的CLR對象。

9、 當我們在列表(比如ListBox)顯示了一個CLR對象列表(比如List)時,如果想在修改List對象後,ListBox也動態的反映這種變化。此時,我們應該使用動態的ObservableCollection對象綁定。而不是直接的更新ItemSource。兩者的區別在於直接更新ItemSource會使WPF拋棄ListBox已有的所有數據,然後全部重新從List加載。而使用ObservableCollection可以避免這種先全部刪除再重載的過程,效率更高。

10、 盡量綁定IList而不是IEnumerable到ItemsControl。

資源:

1、 通常情況下我們會把樣式資源都統一到App.xaml中,這是很好的,便於資源的管理。

2、 盡量把多次重復用到的資源放到App.xaml中。例如某些頁面的資源只會在當前頁面中使用到,那麽可以把資源定義在當前頁面; 因為放在控件中會使每個實例都保留一份資源的拷貝。

3、 如非必要,不要使用DynaicResource,使用StaticResource即可;

動畫:

1、 盡量少的使用Animation:程序啟動時,Animation渲染時會占用一些CPU資源。

2、 降低動畫的幀率:大多數動畫不需要高幀率,而系統默認為60frames/sec,所以可以設定Storyboard.DesiredFrameRate 為更低值。

3、 使用卸載事件卸載不必要的動畫:動畫肯定會占用一定的資源,如果處置方式不當,將會消耗更多的資源,如果你認為它們無用時,你應該考慮如何處理他們,如果不這樣做,就要等到可愛的垃圾回收器先生來回收資源。

4、

圖像:

1、 對Image做動畫處理的時候(如調整大小等),可以使用這條語句RenderOptions.SetBitmapScalingMode(MyImage,BitmapScalingMode.LowQuality),以改善性能。

2、 用TileBrush的時候,可以CachingHint。

3、 預測圖像繪制能力:根據硬件配置的不同,WPF采用不同的Rendering Tier做渲染。下列情況請特別註意,因為在這些情況下,即使是處於Rendering Tier 2的情況下也不會硬件加速。(不全,其余請查閱SDK)

文本:

1、 文字少的時候用TextBlock或者label,長的時候用FlowDocument.

2、 使用元素TextFlow和TextBlock時,如果不需要TextFlow的某些特性,就應該考慮使用TextBlock,因為它的效率更高。

3、 在TextFlow中使用UIElement(比如TextBlock)所需的代價要比使用TextElement(比如Run)的代價高.在FlowDocument中盡量避免使用TextBlock,要用Run替代。

4、 在TextBlock中顯式的使用Run命令比不使用Run命名的代價要高。

5、 把Label(標簽)元素的ContentProperty和一個字符串(String)綁定的效率要比把字符串和TextBlock的Text屬性綁定的效率低。因為Label在更新字符串是會丟棄原來的字符串,全部重新顯示內容。如果字符串不需要更新,用Label就無所謂性能問題。

6、 在TextBlock塊使用HyperLinks時,把多個HyperLinks組合在一起效率會更高。

7、 顯示超鏈接的時候,盡量只在IsMouseOver為True的時候顯示下劃線,一直顯示下劃線的代碼高很多

8、 盡量不使用不必要的字符串連接

9、 使用字體緩存服務提高啟動時間:WPF應用程序之間可以共享字體數據,它是通過一個叫做PresentationFontCache Service的Windows服務實現的,它會隨Windows自動啟動。你可以在控制面板的“服務”中找到這個服務(或在“運行”框中輸入Services.msc),確保這個服務已經啟動。

其他:

1、 用NavigationWindow的時候,盡量Update the client area by object,而不是URI

2、 建立邏輯樹或者視覺樹的時候,遵循Top-Down的原則

3、 使用WPF分析工具分析WPF程序:分析WPF程序是理解其行為很重要的一步,市場上有大量現成的WPF程序分析工具,如Snoop,WPFPerf,Perforator和Visual Profiler,其中Perforator和Visual Profiler是WPF Performance Suite的一部分,要了解這些工具的用法,請去它們的項目主頁。

WPF程序性能