使用 IoCompletionPort 的消息线程
线程通信变得容易!
引言
Windows 具有一个简化的内置机制,用于线程间的通信,使用消息循环。可以使用诸如 GetMessage()
、PeekMessage()
之类的 API 实现此目的。例如:
MSG msg;
PeekMessage(
&msg,
NULL,
0,
0,
PM_NOREMOVE);
while (true)
{
BOOL bRet = GetMessage(
&msg,
NULL,
0,
0);
}
一旦设置了循环,使用 PostThreadMessage()
发送消息。例如:
PostThreadMessage(
nThreadId,
nMsg,
wParam,
lParam);
事实上,基于消息的通信是 Windows 的构建基础。当然,它存在严重的安全性隐患,因为接收者不知道消息的来源,但这又是另一个话题了。
在本文中,我使用了这个概念以及 MFC 宏风格的消息处理程序声明,并将它们封装在一个类中,该类允许您以两种不同的模式发送消息
PostMessage
SendMessage
带超时
代码
为了构建消息循环,我使用了 CreateIoCompletionPort()
、GetQueuedCompletionStatus()
,而不是上述方法。原因如下:
IoCompletionPort
s 速度更快,资源消耗更少。- 没有像其他方法那样的限制,例如线程需要属于同一个桌面等。
好的,我们来看一个例子。顺便说一下,附件中包含一个基于 Visual Studio 的项目,您可以编译并运行它。请查看 DemoThread
类。
首先,从 MsgThread
类派生一个类
// DemoThread.h
class DemoThread : public MsgThread
{
DECLARE_MSG_MAP();
private:
void OnMsgGoGetPizza(
WPARAM wParam,
LPARAM lParam);
};
// DemoThread.cpp
BEGIN_MSG_MAP(DemoThread, MsgThread)
ON_MSG(kMsgGoGetPizza, OnMsgGoGetPizza )
END_MSG_MAP()
void
DemoThread::OnMsgGoGetPizza
(
WPARAM wParam,
LPARAM lParam
)
{
}
在您的代码的其他地方
DemoThread rThread1;
rThread1.Start();
rThread1.PostMessage(
kMsgGoGetPizza,
(WPARAM) 5,
0);
rThread1.Stop();
就这样了。请小心;如果您使用 SendMessage
,如果没有正确设计,可能会陷入死锁。
只需将 MsgHandler.[h,cpp] 和 MsgThread.[h,cpp] 包含在您的项目中即可。希望对您有所帮助。欢迎提出任何意见或建议。