生活随笔
收集整理的這篇文章主要介紹了
对于windows消息机制的体会和理解小纪
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
結論:
對話框、消息框等子窗口是用自已默認的消息循環(huán),而不是重入到父窗的消息循環(huán)!!
主窗阻塞了,第1個子窗負責消息循環(huán),調用線程的消息響應函數(包括主窗、第1個子窗的消息響應函數);
第1個子窗阻塞了,第2個子窗負責消息循環(huán),調用線程的消息響應函數(包括主窗、第1個子窗、第2個字窗的消息響應函數);。。。
子窗是一級一級阻塞下去的,后一個子窗關閉了,才能使前一個子窗的消息響應函數解除阻塞。
如果處在中間的子窗關閉了,它的消息響應函數仍還在阻塞中!只有它后面的子窗都關閉了,它的消息響應函數才會返回。
所以,如果是基于消息來處理事件,比如,網絡SOCKET異步編程,消息處理函數中,有用到消息框MessageBox或對話框,則要小心,以免多個事件消息同時發(fā)生。因為消息框出現(xiàn)后,當前消息處理函數阻塞了,但消息循環(huán)仍在進行,如果有新的消息事件產生,則會運行新的消息處理函數,則有可能會產生不希望的后果。
1.消息隊列:
是屬于線程的,是windows系統(tǒng)為線程創(chuàng)建并維護的一個隊列,用于存放各類消息。 系統(tǒng)自身維護一個系統(tǒng)消息隊列,然后還為每個GUI線程線程維護一個線程專門消息隊列。2.線程:
每個線程默認是沒有消息隊列的,線程只有在第一次調用用戶接口時(比如創(chuàng)建窗口,或者是操作UI元素時),系統(tǒng)才為其創(chuàng)建消息隊列。一個應用程序可以有多個線程,但只能有一個UI線程,默認為主線程,其他子線程是無法操作UI并創(chuàng)建UI元素的。這是windows規(guī)定的
3.
sendmessage只是發(fā)送消息調用消息響應過程,而消息循環(huán)阻塞的話窗口還是不響應響應窗體事件即SendMessage會直接調用該消息的響應函數,即不需要通過消息循環(huán)。
每個ui窗體模態(tài)顯示的話都會創(chuàng)建自己的消息循環(huán),一個線程只有一個活動的消息循環(huán),如果在一個已經有模態(tài)ui(A)線程的線程創(chuàng)建了另一個ui(B)窗體并模態(tài)顯示的話,那么此線程的A消息循環(huán)會阻塞,將運行B線程的消息循環(huán)。
一個窗體的消息循環(huán)里調用本窗體的消息響應過程函數(while循環(huán)語句里調用),而sendmessage是直接調用消息響應過程函數。
4.所以在一個線程里有多個模態(tài)窗體逐個顯示的話,要關閉的話也應該先關閉最后一個顯示的窗體,因為一個線程只有一個活動的消息循環(huán),例如最后一個ShowDialog()的窗體的消息循環(huán)被激活,其他窗體的消息循環(huán)則阻塞,只有關閉掉最后一個窗體其他的窗體才能依次激活自己的消息循環(huán),注意:這里消息循環(huán)和消息過程不是一回事,每個UI窗體控件都有自己的消息循環(huán),消息過程則是在消息循環(huán)里的一個函數,用來處理各種消息對應的事件及邏輯的。
所以多個窗體在一個線程里模態(tài)顯示的話有的窗體close不了是因為不是關閉的最后一個模態(tài)窗體,逐個往之前的遞關才能逐個關閉,否則關閉無效,因為之前的窗體消息循環(huán)斗阻塞了,雖然能通過sendmessage強制發(fā)送消息給消息循環(huán)阻塞的窗體,但是sendmessage的作用實際上只是調用了消息循環(huán)里向相應過程函數,而消息循環(huán)依然被阻塞,所以像close這種消息就不能被響應。
解決辦法:
先關閉最后一個即消息循環(huán)沒有被阻塞而是運行中的窗體,消息循環(huán)(調用者)實際上就是窗體里while語句,循環(huán)語句里包含消息響應過程函數(被調用),每個窗體都有一個自己的消息循環(huán)(即消息循環(huán)函數),及自己的消息響應過程。
多線程創(chuàng)建模態(tài)窗體能解決消息阻塞問題,因為一個線程只有一個活動的ui線程,這樣就異步了。
總結
以上是生活随笔為你收集整理的对于windows消息机制的体会和理解小纪的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。