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