用 UI 多線程處理 WPF 大量渲染的解決方案


眾所周知, WPF 的 UI 渲染是單線程的,所以如果我們異步或者新建線程去進行數據處理的時候,處理完,想要更新 UI 的時候,需要調用一下 Dispatcher.Invoke,將處理完的數據推入到 Dispatcher 中,等待更新界面,不然就會報調用線程無法訪問此對象,因為另一個線程擁有該對象的錯誤。
這就是為什么 WPF 中的大多數對象派生自 DispatcherObject,因為需要 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 操作,所以主窗口沒有被這個大量渲染影響到。
效果

最后

這業務場景還有什么有用的解決方案,請留言教教我!

覺得對你有幫助點個推薦或者留言交流一下唄!

源碼 https://github.com/yijidao/blog/tree/master/WPF/Multithread

WPF 線程模型文檔 https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model?redirectedfrom=MSDN&view=netframeworkdesktop-4.8


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM