天天看點

一個線程何時才能收到Window消息?

你(可能)不知道的

和Windows消息系統打過交道的人都會知道:GetMessage和PeekMessage這兩個API會從視窗的消息隊列中檢索消息,這些消息時由DispatchMessage分發到視窗的。

大部分人也知道:GetMessage和PeekMessage也會自己分發不進入消息隊列的消息。(所有挂起的非隊列消息将會被分發,然後隻有第一個進入隊列的消息會被傳回)

但是大多數人不知道的是:SendMessage也會分發消息。

如果線程T1發送消息給一個屬于線程T2的視窗,則T1線程會進入睡眠狀态直到接收消息的線程處理了這個消息。但是,如果有其他人也發送一個消息到線程T1,則T1則會被喚醒并處理消息,然後會傳回到睡眠狀态。

為什麼這樣設計?

Well,當兩個線程T1和T2一起協同工作的時候,很有可能發生的場景是:線程T1向線程T2發送消息,同時,當線程T2傳回響應給T1之前它就發送消息給T1。是以,線程T1必須準備好接收線程T2發來的消息。

舉個例子,線程T1可能發送一個消息,說:”請告訴你所知道的關于X的一切。” 線程T2接着會發送一個消息給線程T1,說:”這個是一個X”,然後繼續發送另一個消息:說:”這個是另一個X”,以此類推,直到它将所有關于X的資訊告訴給線程T1。

這個時候,線程T1在原始消息傳回的時候,它就知道已經收到了所有線程T2發來的關于X的資訊。這個循環往複的過程,就是DDE服務的運作原理。

另外一個例子

線程T1發送一個消息給T2,然後線程T2在完成消息的處理之前,還需要請求線程T1給予某種幫助,這其實沒有聽起來那麼奇怪。因為你也會做類似的事情,具體來說,就是當你通過發送消息給控件來響應WM_NOTIFY消息的場景,控件就是WM_NOTIFY消息的發送者。(舉個例子,你可能通過向控件發送LVM_GETITEM以擷取被激活的條目資訊,來響應收到的LVN_ITEMACTIVATE通知消息)

是以,請記住:當你發送消息的時候,就會存在潛在的可重入的可能性。

總結

最後

繼續閱讀