1. 渲染系統概述 WPF 採用保留模式渲染系統 (Retained Mode Rendering System),該系統可分為 UI 線程和複合線程兩個主要部分,兩者協作完成 WPF 應用程式的渲染工作。 1.1 立即模式GUI和保持模式GUI 圖形 API 可分為保留模式API 和即時模式API ...
1. 渲染系統概述
WPF 採用保留模式渲染系統 (Retained Mode Rendering System),該系統可分為 UI 線程和複合線程兩個主要部分,兩者協作完成 WPF 應用程式的渲染工作。
1.1 立即模式GUI和保持模式GUI
圖形 API 可分為保留模式API 和即時模式API。 Direct2D 是一種即時模式 API。 WPF 是保留模式 API 的一個示例。
1.1.1. 立即模式GUI
保留模式 API 是聲明性的。 應用程式從圖形基元(如形狀和線條)構造場景。 圖形庫將場景的模型存儲在記憶體中。 為了繪製幀,圖形庫將場景轉換為一組繪圖命令。 在幀之間,圖形庫將場景保留在記憶體中。 若要更改呈現的內容,應用程式會發出命令來更新場景,例如添加或刪除形狀。 然後,該庫負責重繪場景。
每渲染一幀時(很多機器都可以做到1秒鐘60幀),渲染庫需要執行渲染每個元素的指令,所以這種庫無需記住你已經渲染了什麼東西,反正每次都會全部重繪。會持續消耗你的CPU和GPU資源。
即時模式的GUI庫常用於更動態的元素表現,比如實時圖表,動畫,特效,游戲等,任何一個像素的改變,都會快速的呈現給你的用戶。
1.1.2. 保持模式GUI
即時模式 API 是過程性的。 每次繪製新幀時,應用程式都會直接發出繪圖命令。 圖形庫不會在幀之間存儲場景模型。 相反,應用程式會跟蹤場景。
由開發者調用渲染庫的API,適時的重繪需需要改變的元素。這就需要渲染庫有能力記住之前都渲染了什麼東西,所以也會占用更多的記憶體。
保留模式的GUI庫通常更容易使用,使開發更快,但它們也通常也會需要更多的開銷,比如要記住元素的位置、層級、遮蓋情況等等。
保留模式 API 可能更易於使用,因為 API 會為你執行更多工作,例如初始化、狀態維護和清理。 另一方面,它們通常不太靈活,因為 API 施加了自己的場景模型。 此外,保留模式 API 可能具有更高的記憶體要求,因為它需要提供通用場景模型。 使用即時模式 API,可以實現有針對性的優化。
2. 線程模型
2.1. 概述
WPF 應用程式有兩類線程負責渲染:一個用於管理 UI 叫 UI 線程,另一個用於處理渲染叫複合線程,也叫呈現線程。 當 UI 線程接收輸入、處理事件、繪製屏幕和運行應用程式代碼時,複合線程通過隱藏方式在後臺高效運行。
2.1.1. UI線程
UI 線程是 WPF 應用程式最重要的線程。它負責處理所有用戶交互事件,如按鈕單擊、菜單選擇以及鍵盤和滑鼠輸入。它還負責計算 UI 元素的佈局、處理數據綁定、觸發屬性更改等工作。UI 線程是單線程的,這意味著在同一時間只能有一個操作在 UI 線程上運行。
UI 線程在稱為 Dispatcher 的對象內對工作項進行排隊。 Dispatcher 基於優先順序選擇工作項,並運行每一個工作項直到完成。 每個 UI 線程必須具有至少一個 Dispatcher,且每個 Dispatcher 都可精確地在一個線程中執行工作項。
UI 線程也可以啟用多個,由於多線程程式既複雜又難以調試,因此當存在單線程解決方案時,應避免使用多線程程式。
UI 線程的主要職責是:
- 計算佈局和測量視覺(Visual)對象。
- 實現數據綁定和依賴屬性系統。
- 處理用戶輸入和事件。
- 安排和分派渲染工作項給複合線程。
總的來說,UI 線程的工作是計算最終結果,並安排複合線程執行渲染工作。
2.1.2. 複合線程
複合線程負責 WPF 視覺層次結構的實際渲染工作。當應用程式的 UI 需要在屏幕上重新繪製時,複合線程就會介入,包括視窗大小調整、動畫以及任何影響 UI 外觀的操作。
複合線程與 UI 線程緊密協作。UI 線程計算佈局並安排 Visual 對象,複合線程會渲染 Visual 對象,並將其發送給桌面視窗管理器以在屏幕上顯示。
複合線程是一個線程池,包含若幹個工作線程,線程數量通常與系統的 CPU 內核數量相同,可以在多個內核上並行工作,從而提高 WPF 應用程式 UI 操作的性能。
複合線程的主要職責是:
- 生成可視化樹中元素的點陣圖。
- 應用效果(如3D變換、混合模式等)。
- 合成最終的渲染內容發送給桌面視窗管理器。
2.2. UI線程和複合線程協作
UI 線程和複合線程是 WPF 渲染系統的兩個重要部分,它們相互協作完成渲染工作:
- UI線程負責計算佈局、測量元素大小、響應用戶交互等。
- UI線程通過 VisualTarget.Render 方法將渲染工作項分派給複合線程線程池。
- 複合線程中的工作線程並行執行渲染工作,生成點陣圖數據。
- 複合線程將最終的渲染結果提交給桌面視窗管理器顯示。
3. 性能優化
若要生成響應迅速、用戶友好的應用程式,訣竅在於通過保持工作項小型化來最大化 Dispatcher 吞吐量。 這樣一來,工作項就不會停滯在 Dispatcher 隊列中,因等待處理而過時。 輸入和響應間任何可察覺的延遲都會讓界面卡頓無響應,帶來糟糕體驗。
需要註意的是,UI線程不應該執行長時間的操作,否則會導致UI無響應。相反,應該在後臺線程上執行這些任務。
WPF 應用程式在處理大型操作時,如涉及大型計算,或需要查詢某些遠程伺服器上的資料庫。通常情況下,解決方法是在單獨的線程中處理大型操作,讓 UI 線程更多傾向於處理 Dispatcher 隊列中的工作項。大型操作完成後,再通過 Dispatcher 將結果發送到 UI 線程進行安全渲染。
總的來說,UI 線程專註於用戶交互和佈局,而複合線程專註於高效呈現 UI。通過正確地利用這兩個線程,可以構建響應靈敏且高效的 WPF 應用程式。
參考引用:
https://learn.microsoft.com/zh-cn/windows/win32/learnwin32/retained-mode-versus-immediate-mode