迥異和詭異的SendMessage和PostMessage

1       故障現象

故障現象1:可以收到SendMessage()發出的消息,但收不到PostMessage()發出的消息。html

故障現象2:可以收到PostMessage()發出的消息,但收不到SendMessage()發出的消息。緩存

2       兩個比喻

從發送端來講:函數

SendMessage()比如電信系統提供通話服務。ui

若是對方佔線,當即返回。spa

若是對方不佔線,就保持呼叫→接收端接聽→通話→掛斷。在掛斷以前,發送端處於阻塞狀態,不能夠幹別的事。操作系統

 

PostMessage()比如電子郵件系統提供電子郵件服務。orm

發送端把郵件交給電子郵件系統,而後當即返回,就能夠幹別的事了。htm

電子郵件系統將郵件放在隊列緩存區中,緩慢地將郵件發送到接收端的郵箱裏。blog

 

從接收端來講(!!! 關鍵 關鍵 關鍵 !!!)隊列

要接收SendMessage()的消息,必須用手機接聽,到郵箱裏沒法接收此類消息。

要接收PostMessage()的消息,必須到郵箱裏接收,用手機沒法接聽此類消息。

 

1       技術原理

在本文中:

把SendMessage()發送的消息成爲當即消息。

把PostMessage()發送的消息成爲延遲消息。

 

在計算機系統裏,當即消息和延遲消息分別使用徹底不一樣的途徑發送消息,必須採用相匹配的、徹底不一樣的接收方法才能收到消息。

 

                       

1.1      當即消息的收發

爲了接收並處理當即消息,接收端應用程序必須準備一張(消息,處理函數)映射表,以下表所示:

 

消息

處理函數

WM_USER + 1

OnWmUser_1

WM_USER + 2

OnWmUser_2

WM_USER + n

OnWmUser_n

 

當即消息的發送與接收的協做流程以下表:

發送端應用程序

操做系統

接收端應用程序

(消息處理總入口函數)

發送消息

 

 

 

阻塞發送端應用程序

 

 

調用接收端應用程序的消息處理總入口函數

 

 

 

在(消息,處理函數)映射表中搜索與消息相匹配的處理函數,當即調用處理函數。

 

 

向操做系統返回處理結果

 

向發送端應用程序返回處理結果

 

 

解除阻塞發送端應用程序

 

接收消息處理結果

 

 

繼續其它事務

 

 

 

1.2      延遲消息的收發

延遲消息的發送與接收的協做流程以下表:

發送端應用程序

操做系統

接收端應用程序

發送消息

 

 

 

將消息放入接收端應用程序的消息隊列中

 

繼續其它事務

 

從消息隊列中取出消息慢慢處理。

 

2       具體實現

以C++ Builder爲例。

2.1      接收當即消息

要接收當即消息,也就是由SendMessage()發送的消息。

步驟1:聲明並定義消息處理函數

步驟2:聲明和定義(消息,處理函數)映射表

class TForm2 :   public TForm

{

  // 聲明WM_COPYDATA 消息的處理函數

  void __fastcall OnCopyData(const   TMessage &msg);

 

// 受理當即消息 --- 由 SendMessage() 發送的消息

// 聲明和定義(消息,處理函數)映射表

BEGIN_MESSAGE_MAP

  VCL_MESSAGE_HANDLER(WM_COPYDATA, TMessage, OnCopyData);

END_MESSAGE_MAP(TForm)

};

 

2.2      接收延遲消息

要接收延遲消息,也就是由PostMessage()發送的消息。

放置一個TApplicationEvents控件,該控件只能接收延遲消息,沒法接收當即消息。

編寫TApplicationEvents.OnMessage事件處理函數。以下表:

void __fastcall   TForm2::AppEventsMessage(tagMSG &Msg, bool &Handled)

{

  // 若收到延遲消息WM_USER_1

  if (Msg.message == WM_USER_1)

  {

    // 此處編寫消息處理代碼

    // 設立標誌,消息已被處理

    Handled   = true;

  }

  else {

    // 設立標誌,消息未被處理

Handled = false;

  }

}

 

3       結論

SendMessage()和PostMessage()的共性:

都能發送消息。

 

SendMessage和PostMessage的差別:

採用徹底不一樣的途徑發送消息,也要採用徹底不一樣的方法和途徑接收消息。

若接收途徑與發送途徑不匹配,就沒法接收消息。

 

經過SendMessage()發送的消息,發送端發送並必須等待接收端處理,接收端當即處理並向發送端反饋處理結果,無延遲。

經過PostMessage()發送的消息,發送端發送後當即返回,不等待接收端不處理,接收端緩慢地延遲處理。

 

 

SendMessage

PostMessage()

發送端

直接發給接收端

要求接收端當即處理

在接收端處理完畢以前處於阻塞狀態,不能夠幹別的事

能夠當即獲悉接收端的處理結果

消息經由OS緩存到接收端的消息隊列裏

發送完畢當即返回,能夠幹別的事

接收端

當即處理收到的消息

緩慢地從隊列裏取出消息並處理。

 

4       其它

SendMessage和PostMessage的其它特性,網上都有,本文再也不重複與累述。

 

原文出處:https://www.cnblogs.com/micemik/p/11576878.html

相關文章
相關標籤/搜索