PostMessage(異步)和SendMessage(同步)的區別

原文鏈接:https://blog.csdn.net/xiaodan007/article/details/7681031

PostMessage和SendMessage的區別

 

1, PostMessage只把消息放入隊列,不管其他程序是否處理都返回,然後繼續執行,這是個異步消息投放函數。而SendMessage必須等待其他程序處理消息完了之後才返回,繼續執行,這是個同步消息投放函數。而且,PostMessage的返回值表示PostMessage函數執行是否正確;而SendMessage的返回值表示其他程序處理消息後的返回值。這點大家應該都明白。

2, 如果在同一個線程內,PostMessage發送消息時,消息要先放入線程的消息隊列,然後通過消息循環Dispatch到目標窗口。SendMessage發送消息時,系統直接調用目標窗口的消息處理程序,並將結果返回。SendMessage在同一線程中發送消息並不入線程消息隊列。 如果在不同線程內。最好用PostThreadMessage代替PostMessage,他工作的很好。SendMessage發送消息到目標窗口所屬的線程的消息隊列,然後發送消息的線程等待(事實上,他應該還在做一些監測工作,比如監視QS_SENDMESSAGE標誌),直到目標窗口處理完並且結果返回,發送消息的線程才繼續運行。這是SendMessage的一般情況,事實上,處理過程要複雜的多。比如,當發送消息的線程監測到有別的窗口SendMessage一個消息到來時,他直接調用窗口處理過程(重入),並將處理結果返回(這個過程不需要消息循環中GetMessage等的支持)。

3, msdn: If you send a message in the range below WM_USER to the asynchronous message functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its message parameters can not include pointers. Otherwise, the operation will fail.

如果發送的消息碼在WM_USER之下(非自定義消息)且消息參數中帶有指針,那麼PostMessage,SendNotifyMessage,SendMessageCallback這些異步消息發送函數將會調用失敗。 最好不要用PostMessage發送帶有指針參數的消息。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/Aoouch/archive/2007/03/09/1525457.aspx

在調試程序的時候發現,用PostMessage 傳出去的值在我使用的時候已經發生了變化,百思不得其解。

用循環去找一個文件,找到的文件名稱暫存在一個臨時變量裏面,找到之後把這個名稱傳到另外的函數處理,調試發現,處理的總是在我需要的文件後面找到的文件,原因是在我使用的時候那個暫存變量裏面的值已經發生了變化(循環已經處理到了下一步了),

PostMessage 和SendMessage的區別主要在於是否等待其他程序消息處理。PostMessage只是把消息放入隊列,不管其他程序是否處理都返回,然後繼續執行;而SendMessage必須等待其他程序處理消息後才返回,繼續執行。這兩個函數的返回值也不同,PostMessage的返回值表示PostMessage函數執行是否正確,而SendMessage的返回值表示其他程序處理消息後的返回值。

使用SendMessage()可以解決這個問題,只不過在時間效率上會有點下降。

函數原型:

    LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);

    BOOL       PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);

LRESULT 返回消息被處理的結果,在消息被處理之後纔會返回。BOOL 只是返回傳送的結果,是不是已經送到消息隊列。

從網絡上找到一些資料:

   

1       PostMessage 是異步的,SendMessage 是同步的。

          PostMessage 只把消息放到隊列,不管消息是不是被處理就返回,消息可能不被處理;

          SendMessage等待消息被處理完了才返回,如果消息不被處理,發送消息的線程將一直處於阻塞狀態,等待消息的返回。

2          同一個線程內:

             SendMessage 發送消息時,由USER32.DLL模塊調用目標窗口的消息處理程序,並將結果返回,SendMessage 在同一個線程裏面發送消息不進入線程消息隊列;PostMessage 發送的消息要先放到消息隊列,然後通過消息循環分派到目標窗口(DispatchMessage)。

3          不同線程:

             SendMessage 發送消息到目標窗口的消息隊列,然後發送消息的線程在USER32。DLL模塊內監視和等待消息的處理結果,直到目標窗口的才處理返回,SendMessage在返回之前還需要做許多工作,如響應別的線程向它發送的SendMessage().PostMessge() 到別的線程的時候最好使用PostThreadMessage   代替。PostMessage()的HWND 參數可以爲NULL,相當於PostThreadMessage() + GetCrrentThreadId.

4          系統處理消息。

             系統只處理(marshal)系統消息(0--WM_USER),發送用戶消息(用戶自己定義)時需要用戶自己處理。

             使用PostMessage,SendNotifyMessage,SendMessageCallback等異步函數發送系統消息時,參數不可以使用指針,因爲發送者不等待消息的處理就返回,接收者還沒有處理,指針就有可能被釋放了,或則內容變化了。

5 在Windows 2000/XP,每個消息隊列最多隻能存放一定數量的消息,超過的將不會被處理就丟掉。系統默認是10000;:[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows] USERPostMessageLimit

可以修改(我的系統下沒有發現)。

在控制別的應用程序的時候,經常需要等待直到某個功能結束,例如:

    打開一個窗口-->等待直到窗口結束 ,這個時候就可以用到SendMessage

    如果在打開這個窗口後仍然需要對該窗口的界面進行設置,比如Edit的value等等,比如:

       打開一個窗口-->控制窗口的control的屬性

    這個時候就需要PostMessage

使用一個鉤子程序截獲消息後,使用SendMessage把消息發送到主處理程序進行處理,但是在主處理程序還沒有完成任務的時候,被設置鉤子的程序進入了停止的狀態,不可以處理 WM_PAINT, WM_MOVE, .......等的基本信息, 必須要等SendMessage發送出的消息完成後,才能繼續運行,整個界面一片空白,把鉤子消息設置成PostMessage的發送消息形式後,問題解決!

       PostMessage只是把消息放入隊列,不管其他程序是否處理都返回,然後繼續執行;

    而SendMessage必須等待其他程序處理消息後才返回,繼續執行。

       PostMessage的返回值表示PostMessage函數執行是否正確;

    而SendMessage的返回值表示其他程序處理消息後的返回值。

    使用這兩個發送消息函數的最重要的是要看你的程序是否要對消息的滯後性關注否,PostMessage會造成消息的滯後性,而SendMessage則不會,

消息中儘量要傳值,避免傳遞指針

-------------------------------------------------------------------------------------------------------------------

SendMessage函數功能:該函數將指定的消息發送到一個或多個窗口。此函數爲指定的窗口調用窗口程序,直到窗口程序處理完消息再返回,是同步消息投放函數。而函數PostMessage不同,將一個消息寄送到一個線程的消息隊列後立即返回,是異步消息投放函數。
函數原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
參數
  hWnd:其窗口程序將接收消息的窗口的句柄。如果此參數爲HWND_BROADCAST,則消息將被髮送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被髮送到子窗口。
  Msg:指定被髮送的消息。
  wParam:指定附加的消息指定信息。
  IParam:指定附加的消息指定信息。
返回值:返回值指定消息處理的結果,依賴於所發送的消息。
備註:需要用HWND_BROADCAST通信的應用程序應當使用函數RegisterWindowMessage來爲應用程序間的通信取得一個唯一的消息。
  如果指定的窗口是由調用線程創建的,則窗口程序立即作爲子程序調用。如果指定的窗口是由不同線程創建的,則系統切換到該線程並調用恰當的窗口程序。線程間的消息只有在線程執行消息檢索代碼時才被處理。發送線程被阻塞直到接收線程處理完消息爲止。
PostMessage函數功能:該函數將一個消息放入(寄送)到與指定窗口創建的線程相聯繫消息隊列裏,不等待線程處理消息就返回。消息隊列裏的消息通過調用GetMessage和PeekMessage取得。
函數原型:B00L PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
參數
  hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含義的兩個值:
  HWND.BROADCAST:消息被寄送到系統的所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口。消息不被寄送到子窗口。
  NULL:此函數的操作和調用參數dwThread設置爲當前線程的標識符PostThreadMessage函數一樣。
  Msg:指定被寄送的消息。
  wParam:指定附加的消息特定的信息。
  IParam:指定附加的消息特定的信息。
返回值:如果函數調用成功,返回非零值:如果函數調用失敗,返回值是零。若想獲得更多的錯誤信息,請調用GetLastError函數。
備註:需要以 HWND_BROADCAST方式通信的應用程序應當用函數 RegisterwindwosMessage來獲得應用程序間通信的獨特的消息。
  如果發送一個低於WM_USER範圍的消息給異步消息函數(PostMessage.SendNotifyMessage,SendMesssgeCallback),消息參數不能包含指針。否則,操作將會失敗。函數將再接收線程處理消息之前返回,發送者將在內存被使用之前釋放。

速查:Windows NT: 3.1及以上版本; Windows:95及以上版本;Windows CE:1.0及以上版本;頭文件:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實現。

備註的備註:

如果在同一個線程內,PostMessage發送消息時,消息要先放入線程的消息隊列,然後通過消息循環Dispatch到目標窗口。SendMessage發送消息時,系統直接調用目標窗口的消息處理程序,並將結果返回。SendMessage在同一線程中發送消息並不入線程消息隊列。 如果在不同線程內,最好用PostThreadMessage代替PostMessage,他工作的很好。SendMessage發送消息到目標窗口所屬的線程的消息隊列,然後發送消息的線程等待(事實上,他應該還在做一些監測工作,比如監視QS_SENDMESSAGE標誌),直到目標窗口處理完並且結果返回,發送消息的線程才繼續運行。這是SendMessage的一般情況,事實上,處理過程要複雜的多。比如,當發送消息的線程監測到有別的窗口SendMessage一個消息到來時,他直接調用窗口處理過程(重入),並將處理結果返回(這個過程不需要消息循環中GetMessage等的支持)。

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