2010-09-29 75 views
1

多線程編程中的經典建議是在後臺線程上執行繁重的處理器工作,並將結果返回到UI線程以進行小處理(更新標籤等)。如果生成WPF元素本身就是昂貴的操作呢?關於創建昂貴的WPF對象和多線程

我正在與第三方庫合作生成一些激烈的元素,這些元素可能需要0.75s-1.5s來渲染。生成一個並不算太糟糕,但是當我需要創建其中的5個來立即顯示時,它明顯地鎖定了UI(包括進度微調)。不幸的是,沒有其他地方可以創建它們,因爲WPF是線程仿射。我已經試過DispatcherPriority.Background但它不夠。處理這個問題的建議方法是什麼?

+2

使用另一個庫...如果創建一個UIElement的實例需要這麼長時間,它可能相當不好實現 – 2010-09-29 21:49:33

+0

是否這些元素的創建或渲染很昂貴? – Oskar 2010-09-30 13:21:27

回答

1

如果創建的對象派生自Freezable,那麼實際上可以在與UI線程不同的線程上創建它們 - 您只需在工作線程上調用Freeze,然後就可以傳輸他們結束了。但是,對於不能從Freezable派生的項目,這無濟於事。

您是否嘗試過每次創建一個?下面的例子沒有做任何有用的工作,但它確實表明了在小位做了很多工作的基本結構是如何:

int count = 100; 
Action slow = null; 
slow = delegate 
{ 
    Thread.Sleep(100); 
    count -= 1; 
    if (count > 0) 
    { 
     Dispatcher.BeginInvoke(slow, DispatcherPriority.Background); 
    } 
}; 
Dispatcher.BeginInvoke(slow, DispatcherPriority.Background); 

的「工作」這裏是睡了十分之一秒。 (所以如果你用真正的工作來替代它,你會得到相同的行爲。)這樣做的次數是100次,所以這是總共10秒的「工作」。用戶界面在整個過程中保持合理的響應 - 例如拖動窗口變得不那麼流暢,但它非常實用。將這兩個背景優先級更改爲正常,並鎖定應用程序。

這裏的關鍵是我們在完成排隊的每一小部分工作後最終返回 - 我們最終調用Dispatcher.BeginInvoke 100次而不是一次。這使得用戶界面有機會定期迴應投入。