来自目标线程的 PostThreadMessage
Posted
技术标签:
【中文标题】来自目标线程的 PostThreadMessage【英文标题】:PostThreadMessage from target thread 【发布时间】:2013-07-29 18:52:12 【问题描述】:今天,我看到了这样的代码:
void Foo()
MyMsgStruct myMsg;
/* omission for simplicity */
/* send to update thread */
PostThreadMessage(myThreadId, myMessage, (WPARAM)myMsg, NULL);
当Foo()
与myThreadId
从同一线程调用时会发生什么,即从应该是目标线程的同一线程?这是性能问题还是只是糟糕的编写代码或两者兼而有之?
我相信它可能会影响性能,因为我相信它会将消息排队到线程的队列中,而不是只做它应该做的事情,因此会稍微减慢程序的速度。
线程安全不是我关心的这个问题。
【问题讨论】:
这里有更多关于 PostThreadMessage 的背景信息:codeproject.com/Articles/225755/PostThreadMessage-Demystified 附注:发布引用自动变量(如myMsg
)的消息时要小心 - 除非它是标量整数变量并且在 wParam
中按值传递,否则自动变量可能会得到在接收线程能够检索和处理消息之前被销毁。当发布到同一个线程时尤其如此,因为在Foo()
返回和myMsg
被破坏之前不会发生任何消息处理(除非存在消息泵循环但此处未显示)。堆分配解决了这个问题。
【参考方案1】:
没什么特别的,只是需要一段时间才能调用任何应该运行的代码。只是延迟,并不一定会使您的程序变慢。有时您是故意这样做的,例如想要响应 Windows 消息但立即这样做会导致重新进入问题。
然而,几乎总是应该避免使用 PostThreadMessage。当线程也创建窗口时,会发生非常糟糕的事情,几乎总是这样,因为您倾向于发布到 UI 线程以获取代码以更新窗口。每当进入模态循环时,消息就会落入比特桶中。就像用于调整窗口大小的那个。或显示 MessageBox。总是倾向于张贴到一个窗口,而不是,消息不会丢失。请检查 PostMessage() 的返回值。
创建一个虚拟的不可见窗口,其窗口过程处理这些消息通常是一个好主意。您现在还可以检查是否需要发布或可以直接使用 SendMessage 执行。比较 GetWindowThreadProcessId 和 GetCurrentThreadId。
【讨论】:
只有1个窗口,线程是工作线程,所以UI线程没有危险。我读过很多关于PostThreadMessage()
和 windows 的问题,是的,它产生的问题比它解决的要多。
不,一个窗口足以引起这个问题。只是不要这样做。如果您不想创建隐藏窗口,则只需使用该窗口即可。【参考方案2】:
无论是哪个线程调用PostThreadMessage()
,消息都会进入目标线程ID的消息队列。线程向自己发布消息是完全有效的。当线程将其消息队列泵入新消息时,将处理该消息。有时一个线程可能真的希望有一个延迟的动作,所以发布的消息是有好处的。如果一个线程想立即做某事,调用PostThreadMessage()
没有意义,直接执行操作即可。对于线程消息,没有与 SendMessage()
等效的选项。
【讨论】:
以上是关于来自目标线程的 PostThreadMessage的主要内容,如果未能解决你的问题,请参考以下文章
当前线程为主线程,我想用PostThreadMessage 给当前线程(主线程)发送消息,没有反映这是为啥呀?
未调用 MFC 的 CWinThread::PostThreadMessage 处理程序