Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 如何从不同的线程执行SendMessage?_Windows_Winapi - Fatal编程技术网

Windows 如何从不同的线程执行SendMessage?

Windows 如何从不同的线程执行SendMessage?,windows,winapi,Windows,Winapi,当我们发送消息时,“如果指定的窗口是由调用线程创建的,那么窗口过程将作为子例程立即调用”。 但是“如果指定的窗口是由不同的线程创建的,则系统将切换到该线程并调用相应的窗口过程。只有当接收线程执行消息检索代码时,才会处理线程之间发送的消息。”(摘自SendMessage)的MSDN文档) 现在,我不明白如何(或者更恰当地说,何时)调用目标windows过程。当然,目标线程不会被抢占(程序计数器不会更改)。我假设调用将在某个等待函数(如GetMessage或PeekMessage)期间发生,这是真的

当我们发送消息时,“如果指定的窗口是由调用线程创建的,那么窗口过程将作为子例程立即调用”。 但是“如果指定的窗口是由不同的线程创建的,则系统将切换到该线程并调用相应的窗口过程。只有当接收线程执行消息检索代码时,才会处理线程之间发送的消息。”(摘自
SendMessage
)的MSDN文档)

现在,我不明白如何(或者更恰当地说,何时)调用目标windows过程。当然,目标线程不会被抢占(程序计数器不会更改)。我假设调用将在某个等待函数(如
GetMessage
PeekMessage
)期间发生,这是真的吗?这个过程在什么地方有详细的记录


更新:其背后的基本原理由
GetQueueStatus()
MsgWaitForMultipleObjects()的
QS\u SENDMESSAGE
标志解释:


这以及MSDN文档中的附加注释意味着另一个线程发送的消息实际上已发布到队列。然后,只要调用了
GetMessage
PeekMessage
,它将在任何其他已发布消息之前被处理,直接发送到窗口过程。

简短回答:当目标线程调用GetMessage(或PeekMessage)后再调用DispatchMessage,然后接收并处理来自另一个线程的SendMessage

我不确定收到的SendMessage是否会抢占队列中的其他消息。无论哪种方式,从一个线程到另一个线程的SendMessage都类似于说:“将此消息发布到另一个线程的消息队列。在该线程完成处理后返回”

现在,请回答您没有要求的问题:


通常,当我在主UI线程和工作线程之间编程交互时,我会尽量避免使用SendMessage。如果不小心,可能会出现两个线程彼此死锁的情况。(考虑这样一种情况:主线程调用WaitForSingleObject以等待工作线程完成,但工作线程在将消息发送回UI线程时被阻止)。

每个窗口都与一个线程关联。您可以使用
GetWindowThreadProcessId
检索每个窗口的线程。如果您从另一个线程向windows发送有关
PostThreadMessage
的消息,则该消息将放置在该线程的消息队列中。线程必须有一个get message循环(例如使用
GetMessage
)来获取消息并将其分派到窗口的窗口过程

如果您调用
SendMessage
,而不是
PostThreadMessage
,则直接调用Windows过程,而不将其放入消息队列中。一些未排队的消息也会立即发送到目标窗口过程,绕过系统消息队列和线程消息队列。(见附件)。如果您想从另一个窗口(控件)提供一些信息,例如在处理另一条消息时从另一个控件读取文本,则使用
SendMessage
而不是
PostThreadMessage
的主要原因。只有在真正需要的时候,你才应该这样做。因此,如果使用
SendMessage
从另一个线程向windows发送消息,则当前线程必须被阻止一段时间


如果可能的话,最好使用
PostThreadMessage
SendMessageCallback
而不是
SendMessage

我发现这里有些混乱

根据MSDN文档,当您出于消息处理的目的触摸当前线程的消息队列时(例如,如果您调用
PeekMessage
GetMessage
),则所有待发送(即非排队)处理来自其他线程的消息-传递到
WndProc
-然后检查消息队列,因此:

  • 发送的消息从不经过
    DispatchMessage
    ,而是尽快处理:
    • 在当前线程中,它们被简单地传递到
      WndProc
    • 在另一个线程中,它们在任何已发布消息处理之前被处理
  • 为了能够处理发送的消息,目标线程仍然需要一个消息泵
  • PostThreadMessage
    只执行它所声明的操作—在线程队列中发布消息—此类消息不会定向到任何窗口,必须进行明确的处理
  • DispatchMessage
    处理的唯一消息是由
    PostMessage
    或某些系统设施(计时器、事件、用户输入等)创建的消息
  • 要避免死锁,请在不同线程之间使用
    SendNotifyMessage
    SendMessageTimeout
    SendMessageCallback
    而不是普通的
    SendMessage

为了进一步参考,请研究MSDN
PeekMessage
条目的备注部分。

OK,那么从不同的线程发送消息(在我的情况下,实际上甚至是不同的进程)就像使用“阻塞后消息”一样?我的问题是,我必须使用MsgWaitForMultipleObjectsEx和PeekMessage(在Windows CE上)创建一个辅助消息循环。不确定您真正想做什么,但如果是用于进程间通信,那么您可能应该使用COM。我必须克服我正在使用的系统的一些限制,我必须通过阻塞等待消息(当然是异步的)来模拟同步场景。与此同时,我必须对壳牌公司发送的信息做出响应。由于某些原因,在某些情况下,我们的自定义shell会一直挂起,直到我收到该消息,我不明白为什么。。。然而,你对SendMessage的回答令人满意,因为我有疑问。我怀疑,正如另一个回答所说
QS_SENDMESSAGE
 A message sent by another thread or application is in the queue.