PostMessage(异步)和SendMessage(同步)的区别

文章转自:原文处

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等的支持)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C#中SendMessagePostMessage的参数传递 在C#中可以使用Window API提供的SendMessagePostMessage来传递参数。两者的区别简单介绍下:返回值的不同,我们先看一下 MSDN 里的声明: LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); BOOL PostMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); 其中 4 个参数的意义是一样的,返回值类型不同(其实从数据上看他们一样是一个 32 位的数,只是意义不一样),LRESULT 表示的是消息被处理后的返回值,BOOL 表示的是消息是不是 Post 成功。 2、PostMessage异步的,SendMessage同步的。 PostMessage 只把消息放入队列,不管消息是否被处理就返回,消息可能不被处理;而 SendMessage 等待消息被处理完了之后才返回,如果消息不被处理,发送消息的线程将一直被阻塞。 3、如果在同一个线程内,SendMessage 发送消息时,由 USER32.DLL 模块调用目标窗口的消息处理程序,并将结果返回。SendMessage 在同一线程中发送消息并不入线程消息队列。PostMessage 发送消息时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。 如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在 USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。SendMessage 在返回前还做了很多工作,比如,响应别的线程向它 SendMessage。Post 到别的线程时,最好用 PostThreadMessage 代替 PostMessagePostMessage 的 hWnd 参数可以是 NULL,等效于 PostThreadMessage + GetCurrentThreadId。Post WM_QUIT 时,应使用 PostQuitMessage 代替。 4、系统只整编(marshal)系统消息(0 到 WM_USER 之间的消息),发送用户消息(WM_USER 以上)到别的进程时,需要自己做整编。 用 PostMessage、SendNotifyMessage、SendMessageCallback 等异步函数发送系统消息时,参数里不可以使用指针,因为发送者并不等待消息的处理就返回,接受者还没处理指针就已经被释放了。 5、在 Windows 2000/XP 里,每个消息队列最多只能存放 10,000 个 Post 的消息,超过的还没被处理的将不会被处理,直接丢掉。这个值可以改得更大:[HKEY_LOCAL_MACHINE/SOFTWARE/ Microsoft/Windows NT/CurrentVersion/Windows] USERPostMessageLimit,最小可以是 4000。 PostMessage只负责将消息放到消息队列中,不确定何时及是否处理 SendMessage要等到受到消息处理的返回码(DWord类型)后才继续 PostMessage执行后马上返回 SendMessage必须等到消息被处理后才会返回。
### 回答1: PostMessageSendMessage 都是 JavaScript 中用来在不同窗口或框架之间进行通信的方法。 PostMessage 方法允许开发人员在两个不同域之间发送消息,而 SendMessage 方法则是在同一域之间发送消息。 这两种方法都可以在父窗口和子窗口之间进行通信,也可以在不同页面之间进行通信。 ### 回答2: postmessagesendmessage都是Windows API中的函数,用于在不同的应用程序之间发送消息。它们之间有一些区别postmessage函数是异步的,它会将消息放入目标窗口的消息队列中,并立即返回。这意味着,发送消息的线程不会等待目标窗口处理消息,而是继续执行自己的代码。这种异步的消息传递方式适用于需要快速发送消息并不需要等待结果的情况。 而sendmessage函数是同步的,它会直接调用目标窗口的消息处理函数,并等待这个函数返回后继续执行。这意味着,发送消息的线程会阻塞在sendmessage函数的调用上,直到目标窗口处理完消息并返回结果。这种同步的消息传递方式适用于需要及时获取结果的情况。 由于postmessage异步的,所以在发送完消息后不能立即获得目标窗口的处理结果。如果需要知道消息处理的结果,可以使用sendmessage。但由于sendmessage同步的,如果目标窗口的消息处理函数需要花费很长时间,那么发送消息的线程也会被阻塞同样长的时间。 在实际应用中,通常优先考虑使用postmessage,因为它具有较高的执行效率。只有在确实需要及时获取目标窗口的处理结果时,才使用sendmessage。另外,需要注意的是,对于跨进程的消息传递,只有sendmessage函数可以实现,而postmessage只能用于同一进程内的消息传递。 ### 回答3: postmessagesendmessage都是Windows API中的函数,用于在不同的窗口之间发送消息。 postmessage函数是发送异步消息的函数,它会将消息放入接收窗口的消息队列中,然后立即返回。该函数不会等待接收窗口处理完消息,而是继续执行后续的代码。这意味着发送的消息不会影响到发送窗口的执行流程。因此,postmessage适用于不需要立即得到响应的情况,比如向其他应用程序发送消息。 sendmessage函数则是发送同步消息的函数,它会将消息发送给接收窗口,并且会一直等待接收窗口处理完该消息后才会返回。这意味着发送消息的窗口必须等待接收消息的窗口处理完消息后才能继续执行后续的代码。因此,sendmessage适用于需要立即得到响应或需要对消息的处理结果进行判断的情况,比如向同一应用程序的其他窗口发送消息。 总结来说,postmessage异步地发送消息,不等待接收窗口处理消息;sendmessage同步地发送消息,等待接收窗口处理消息后才返回。选择使用哪个函数要根据具体的需求来决定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值