關於GUI線程和worker線程

1.   所謂的worker線程,是指完全不牽扯到圖形用戶界面(GUI),純粹做運算的線程。

2.   微軟的多線程模型:
Win32說明文件一再強調線程分爲GUI線程和worker線程兩種。GUI線程負責建造窗口以及處理主消息循環。Worker負責執行純粹的運算工作,如重新計算或重新編頁等,這些運算工作會導致主線程的消息隊列失去反應。一般而言,GUI線程絕不會去做那些不能夠馬上完成的工作。
GUI線程的定義是:擁有消息隊列的線程。任何一個特定窗口的消息總是被產生這一窗口的線程抓到並處理。所有對此窗口的改變也都應該由該線程完成。
如果worker線程也產生了一個窗口,那麼就會有一個消息隊列隨之被產生出來並且附着到此線程身上,於是worker線程搖身一變成了GUI線程。這裏的意思是:worker線程不能夠產生窗口、對話框、消息框,或任何其他與UI有關的東西。
如果一個worker線程需要輸入或輸出錯誤信息,它應該授權給UI線程來做,並且將結果通知給worker線程。
消息隊列是一個鏈表,只有在必要的時候,纔有元素產生出來。具體的關於消息隊列的數據結構,可以參考相關的windows文檔。

3.   在Win32中,每一個線程有它自己專屬的消息隊列。這並不意味着每一個窗口有它自己的消息隊列,因爲一個線程可以產生許多窗口。如果一個線程停止迴應,或是它忙於一段耗時的計算工作,那麼由它產生的窗口統統都會停止迴應,但系統中的其他窗口還會繼續正常工作。
以下是一個非常基本的規則,用來管理Win32中的線程、消息、窗口的互動:
所有傳送給某一窗口之消息,將由產生該窗口之線程負責處理。
比方說,使用SetWindowText來更新一個Edit框的內容,其實就是發出了一個WM_SETTEXT消息給edit窗口函數。推而廣之,每一個控件都是一個窗口,都擁有自己的窗口函數。
對窗口所作的一切事情基本上都會被該窗口的窗口函數處理,並因此被產生該窗口的線程處理。

當需要發送一個消息時,Windows會自動計算出哪一個線程應該接收到消息(以便確定該消息實體應該掛在在哪一個線程的消息隊列中)。同時,windows還會確定線程應該如何被告知有這麼一個消息進來。一共有四種可能:
(1)如果屬於同一線程,使用SendMessage傳遞消息,則直接調用窗口函數。
(2)如果屬於同一線程,使用PostMessage傳遞消息,則把消息放在消息隊列中然後立即返回。
(3)如果不屬於同一線程,使用SendMessage傳遞消息,則切換到新線程中並調用窗口函數。在該窗口函數結束之前,SendMessage不會返回。
(4)PostMessage立刻返回,消息則被放到另一線程的消息隊列中。
當我send一個消息給另一線程掌握的窗口時,系統必須做一次context switch,切換到另一線程去,調用該窗口函數,然後再做一次context switch切換回來,相對一般的函數調用而言,期間的額外負擔較大。如果在MDI中,爲每個子窗口分配一個線程,那麼該子窗口的所有資源——包括畫刷,DC,調色板等等都屬於線程的資源。此時爲線程做context switch時會代價很大。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章