用 UI 多執行緒處理 WPF 大量渲染的解決方案
阿新 • • 發佈:2022-03-04
眾所周知, WPF 的 UI 渲染是單執行緒的,所以如果我們非同步或者新建執行緒去進行資料處理的時候,處理完,想要更新 UI 的時候,需要呼叫一下 Dispatcher.Invoke,將處理完的資料推入到 Dispatcher 中,等待更新介面,不然就會報呼叫執行緒無法訪問此物件,因為另一個執行緒擁有該物件的錯誤。
但是工作中,有時候會遇到 UI 密集型的情況,也就是介面不停渲染導致介面出現卡住的情況,這時候就是 Dispatcher 忙不過來了,一般這時候,都會想要用多執行緒來渲染介面,但是一個 Dispatcher 只能為一個執行緒服務,所以我一般會將這種 UI 密集型的介面,單獨放到一個彈窗中,再新建一個 UI 執行緒並指定 Dispatcher 來渲染。
樣例程式碼
程式碼也很簡單,我直接貼啦!
我在介面中放了兩個按鈕,一個用來開啟負責大量渲染的視窗,一個用來關閉該視窗。
Window w = null; newWindowButton.Click += (sender, args) => { var thread = new Thread(() => { w = new Window { Content = new LargeRenderView(), Width = 1200, Height = 1000 }; w.Show(); Dispatcher.Run(); // 執行 Dispatcher,為新建的 UI 執行緒服務 }); thread.SetApartmentState(ApartmentState.STA); // // 指定執行緒為單執行緒模式 thread.Start(); }; closeWindowButton.Click += (sender, args) => { w.Close(); if (w == null) return; if (w.Dispatcher.CheckAccess()) w.Close(); else w.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadStart(w.Close)); };
效果
可以看到新彈窗因為大量渲染,滑鼠一直在轉圈,無法操作,但是主視窗還是可以進行 UI 操作,所以主視窗沒有被這個大量渲染影響到。