WPF與WinForm對比多執行緒程式設計優化是關鍵

2022-04-29 04:54:11 字數 2337 閱讀 2770

it168技術】很多人問過我這樣乙個問題:wpf和以前的winform有什麼區別?我之前的回答一直是:沒什麼區別,僅僅是表示層用xaml封了層皮,使得windows看起來更炫了。

今天(確切的說是昨天),我終於發現了我膚淺。首先我要澄清一下,wpf較之winform的先進之處不止一點點。

對於wpf,很多人都以為這是微軟的乙個小玩具,充其量就是讓vista和win7的表示層更炫了,然後就會吸引人們去購買——當然了,我相信多數人購買wim7的動機並不在乎它的核心做了什麼變動...

言歸正傳...

wpf將windows表示層發展至用宣告式語言進行開發,並且融入大量的動畫和特效,使得在win32中極難做到的富客戶端應用能在wpf中信手拈 來,同時用向量圖取代位圖,引入路由事件(routedevent)對元素樹進行多層監聽,通過依賴屬性(dependencyproperty)動態變 更控制項樹等,這些都是表面上我們所看到的。不過這些不是我今天想說的重點,何況有不少牛人的研究要比我深入多了,實在是自慚形穢啊,今天我只是承認錯誤來 的。

在眾多wpf對於winform的優勢中,令我意識到我之前的錯誤的一點就是wpf對於多執行緒程式設計的優化。

在 winform程式開發時,一旦涉及多執行緒操作,我們一般不可能沒有見過invalidoperationexception這個異常。這個異常的出現多 數情況是由於worker執行緒(子執行緒)修改主線程式控制件(或物件)的屬性而導致的非法操作,當然這種做法也非每次都會失敗,這主要取決於子執行緒想要操作的 物件是不是執行緒安全的。

無論是windows窗體還是wpf,問題的成因都很簡單:windows控制項使用的是元件物件模型(component object model,com)單執行緒單元(single-threaded apartment,sta)模型,因為其底層的控制項是單元執行緒(apartment-threaded)的。此外,很多控制項都用訊息幫浦(message pump)來完成操作。因此,這種模型就需要所有呼叫該控制項的方法都和建立該控制項的方法位於同乙個執行緒上。

winform控制項提供了 invokerequired屬性來判斷當前執行緒是不是建立此控制項的執行緒。一旦控制項建立完成,那麼invokerequired的效率將會不錯,且也能保 證安全。不過若是目標控制項尚未被建立(此時,雖然c#物件已經存在,不過其底層的視窗控制代碼仍舊為null),那麼invokerequired則可能會耗 費比較長的時間。(它會從下至上遍歷整個控制項樹,直到找到乙個可以承載此控制項且已經例項化並被建立了的父控制項,這種做法可以保證子控制項將會與父控制項在同一 個執行緒上建立。找到合適的父控制項之後,框架即可執行同樣的檢查,比較當前執行緒的id和建立該父控制項的執行緒的id。)。若是框架無法找到任何乙個已建立的父 窗體,那麼則需要找到一些其他型別的窗體。若在層次體系中無法找到可用的窗體,那麼框架將開始尋找暫存窗體(parking window),暫存窗體讓你不會被某些win32 api奇怪的行為所干擾。簡而言之,有些對窗體的修改(例如修改某些樣式)需要銷毀並重新建立該窗體。暫存窗體就是用來在父窗體被銷毀並重新建立的過程中 用來臨時儲存其中的控制項的。在這段時間內,ui執行緒僅執行於暫存窗體中。

「通常,wpf 應用程式從兩個執行緒開始:乙個用於處理呈現,乙個用於管理 ui。呈現執行緒有效地隱藏在後台執行,而 ui 執行緒則接收輸入、處理事件、繪製螢幕以及執行應用程式**。」

「ui 執行緒對乙個名為 dispatcher 的物件內的工作項進行排隊。 dispatcher 基於優先順序選擇工作項,並執行每乙個工作項,直到完成。每個 ui 執行緒都必須至少有乙個 dispatcher,並且每個 dispatcher 都只能在乙個執行緒中執行工作項。」

——msdn

wpf開始設計的時候,就將多執行緒的問題考慮了進去,上述很多過程都 得到了簡化。這得益於dispatcher類的使用,每個執行緒都有乙個dispatcher。在第一次訪問某個控制項的dispatcher時,類庫將察看 該執行緒是否已經擁有了dispatcher。若已經存在,那麼直接返回。如果沒有的話,那麼將建立乙個新的dispatcher物件,並關聯在控制項及其所 在的執行緒之上。dispatcher提供了類似invokerequired的方法(checkaccess)【實際上並不提倡使用此方法,且在目前的 wpf中此方法已經被取消】。這個方法只是比較執行緒的id,所以會很快。

另外,dispatcher提供了優先佇列(總共11個 priority,主要是用於wpf中ui的層次結構設計,比如動畫的優先順序就是最高的);非同步呼叫(winform中的 control.begininvoke和control.endinvoke也提供非同步功能);dispatchertimer (使用 dispatchertimer 而不是使用 system.timers.timer 的原因是 dispatchertimer 與 dispatcher 執行於相同的執行緒,並且可以在 dispatchertimer 上設定 dispatcherpriority),簡化了開發多執行緒gui程式

Winform和WPF簡單對比

winforms 指令碼都是基於c winforms是做客戶端軟體,winform是.net開發平台中對windows form的一種稱謂。是一種基於c 的軟體開發平台。如果要新建乙個視窗檔案,wpf中為windows或者usercontrol,檔案以.xaml和.cs結尾。但在winform中,則...

對比MFC和Winform及WPF

mfc 生成本機 自然是很快。可是,訊息迴圈,減緩了介面顯示速度。winform 封裝了 win32 的api,多次進行p invoke 操作 大部分使用p invoke操作封裝 速度慢 wpf是一種新的模型,不再使用win32 模型,自己新建模型,使用dx 作為新的顯示技術,直接訪問驅動程式,加快...

Python爆力破解rar密碼並對比多執行緒的效率

要破解首先得有密碼本,這個重複造輪子是沒必要滴。網上有很多同鞋已經造了很多好用的輪子,這裡選了骨灰家的輪子 linux版 隨便生成了乙個密碼本,共約1800多個密碼,檔名為dic,其實就是個文字檔案,每行乙個密碼。並把我正確的密碼藏在檔案最後用來測試軟體。from threading import ...