工作线程没有消息循环(MFC、windows)。我们可以让它接收消息吗?
Posted
技术标签:
【中文标题】工作线程没有消息循环(MFC、windows)。我们可以让它接收消息吗?【英文标题】:Worker thread doesn't have message loop (MFC, windows). Can we make it to receive messages? 【发布时间】:2011-07-12 08:52:09 【问题描述】:Mfc 提供工作线程和 UI 线程。 UI 线程启用了消息接收功能(发送、发布)。是否可以让工作线程也接收消息。
【问题讨论】:
那为什么不使用 UI 线程呢?无论名称如何,您都不必包含任何 UI 内容。事实上,比我更了解的人建议将所有 UI 内容放在主线程中,因此 UI 线程将是“带有消息泵的辅助线程”。 【参考方案1】:反复调用CWinThread::PumpMessage()
,直到它返回WM_QUIT
消息。
【讨论】:
你将如何发送消息? sendmessage/postmessage 需要窗口句柄。我相信 postthreadmessage 会做的事情。GetMessage 可以做的事情。 您可以将 CThread 对象的引用传递给 ::PostThreadMessage(),也可以调用 CThread::PostThreadMessage()。 SendMessage() 不能用于向另一个线程发送消息。 PostThreadMessage() 仅将消息放入队列中。您无法知道对应操作是如何或何时完成的,因为线程异步处理消息。 你会后悔尝试将消息发布到没有窗口的队列。创建一个隐藏窗口作为这些消息的接收者。 如果窗口句柄为NULL,消息不是通过它的message-map发送给CWinThread派生类的成员函数吗?为什么要寻址一个窗口? CWinThread 具有与 CWnd 相同的基类!尝试将 MSG 结构的 hwnd 字段设置为 NULL 的 CWinThread::PostMessage()。 在任何情况下,永远不要从另一个线程调用 CWnd::SendMessage() 到窗口。事情可能会因此而变得一团糟。 MFC 的 Debug 版本将 ASSERT。【参考方案2】:看来您需要一个线程,它可以处理来自另一个线程的多条消息。另一个线程将向该线程的消息队列添加消息。好吧,在这种情况下,您可以使用PeekMessage
启动一个循环,最终会创建一个隐藏窗口,然后使用GetMessage
获取消息。其他线程将使用 PostThreadMessage
和线程 ID(具有 Peek/GetMessage 的那个)和消息代码 LPARAM
、WPARAM.
就像(语法不正确):
TheProcessor()
MSG msg;
PeekMessage(&msg,...);
while(GetMessage(&msg...)
/* switch case here */
线程将调用PostThreadMessage
- 有关详细信息,请参阅 MSDN。
当您需要发送超过 LPARAM/WPARAM 可以容纳的数据时,您最终需要在堆上分配它们,然后在自定义消息循环中处理消息后删除。这将是麻烦和错误的。
但是...我建议您在std::queue/deque
或其他DS 之上拥有自己的课程,您可以在其中添加AddMessage
/PushMessage
和PopMessage
(或任何您喜欢的名称) .您需要使用SetEvent
、WaitForSingleObject
来触发循环中的新消息(请参阅implementation here 之一。您可以将其设为一种数据类型的通用类,或将其设为模板类——这将支持任何数据——类型(您的底层 DS (queue
) 将使用相同的数据类型)。您也不必担心堆和删除。这不太容易出错。但是,您可能必须处理 MT 问题。
使用 Windows 事件涉及内核模式转换(因为事件是命名/内核对象),您可能希望使用作为用户对象的条件变量。或者您可以直接使用 VC10 中可用的并发运行时库中的unbounded_buffer
类。见this article(跳转到unbounded_buffer
)。
【讨论】:
【参考方案3】:是的,您可以在工作线程上创建消息队列。您需要在该线程上运行消息泵。
【讨论】:
GetMessage 可以做的事情。以上是关于工作线程没有消息循环(MFC、windows)。我们可以让它接收消息吗?的主要内容,如果未能解决你的问题,请参考以下文章