多线程之间可以使用WINDOWS消息机智来进行消息通讯。
一个线程原本是没有消息队列的,调用任何与消息相关的API会自动初始化线程消息队列相关的数据结构。
自定义Windows消息
#define MY_MSG (WM_USER+1)
注:
(1)为了防止用户定义的消息ID与系统的消息ID冲突,Microsoft定义了一个宏 #define WM_USER 0X0400.
(2)小于WM_USER的ID被系统使用,大于WM_USER的ID被用户使用。
PostThreadMessage将信息发送到指定线程
BOOL PostThreadMessage(DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam);
目标线程通过GetMessage()方法来接收消息。
参数:
idThread: 接收消息的线程id
Msg: 指定被寄送的消息
wParam: 指定附加的消息特定的信息
lParam: 指定附加的消息特定的信息
返回值:
成功:返回非零
失败:返回零
调用GetLastError返回1444可能是线程不存在消息列队
GetMessage从消息列队中获取消息
BOOL GetMessage(LPMSG lpMsg.
HWND hWnd,
UINT wMsgFilterMin,
UINT sMsgFilterMax);
目标线程通过GetMessage()方法来接收消息,若无消息则阻塞。
参数:
lpMsg: 接收消息的线程id
hWnd: 取得消息的窗口的句柄,当NULL 时获取所属线程的消息
wMsgFilterMin: 指定被检索的最小消息值的整数
sMsgFilterMax: 指定被检索的最大消息值的整数
返回值:
(1)如果函数取的时WM_QUIT之外的其他消息,返回非零值。否则返回值是零。
(2)错误返回-1。
(3)调用GetLastError函数获取错误。
PeekMessage窥探消息队列中的消息
BOOL PeekMessage(LPMSG lpMsg,
HWND hWnd,
UINT wMSGfilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg);
返回:
(1)如果消息可得到,返回非零值。
(2)如果消息未得到,返回零。
参数:
lpMsg:接收消息的线程id。
hWnd:获得消息的窗口的句柄,NULL时获取所属线程的消息。
wMSGfilterMin:指定被检索的最小消息值的整数。
wMsgFilterMax:指定被检索的最大消息值的整数。
wRemoveMsg:此参数可取下列值之一:
(1)PM_NOREMOVE 获取消息后不从队列里删除。
(2)PM_REMOVE 获取消息后从列队里删除。
(3)PM_NOYIELD 使系统不释放等待调用程序空闲的线程
(4)可将PM_NOYIELD随意组合到PM_NOREMOVE/PM_REMOVE.
PeekMessage / GetMessage的区别
函数 | 是否立即返回 | 返回值 | 处理 |
GetMessage | 若取不到消息,则线程就会被操作系统挂起,阻塞。 | 有消息:TRUE 无消息:FALSE | 消息被取出后,就从消息队列中将其删除。 |
PeekMessage | 立即返回 | 有消息:(不为WM_QUIT)返回TRUE。 WM_QUIT:返回FALSE. 无消息:不返回 | PM_REMOVE:消息被取出并从消息队列中删除。 PM_NOREMOVE:窥探,不删除。 |
#include<windows.h>
#include<stdio.h>
#define MY_MSG WM_USER+1
DWORD WINAPI threadFun1(LPVOID paramer);
DWORD WINAPI threadFun2(LPVOID paramer);
int main()
{
DWORD threadID = 0;
HANDLE hThread1 = CreateThread(NULL, 0, threadFun1, NULL, 0, &threadID);
HANDLE hThread2 = CreateThread(NULL, 0, threadFun2, (LPVOID)threadID, 0, NULL);
HANDLE Arry[] = { hThread1,hThread2 };
WaitForMultipleObjects(2, Arry, TRUE, INFINITE);
printf("End!\n");
return 0;
}
DWORD WINAPI threadFun1(LPVOID paramer)
{
MSG msg;
//while (GetMessage(&msg, NULL, 0, 0))
//{
// switch (msg.message)
// {
// case MY_MSG:printf("接收消息为:%d\n", msg.wParam); break;
// }
//}
//printf("接收到退出消息,退出!\n"); return 0;
//PeekMessage
while (true)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case MY_MSG:printf("接收消息为:%d\n", msg.wParam); break;
case WM_QUIT:printf("接收到退出消息,退出!\n"); return 0;
}
}
}
return 0;
}
DWORD WINAPI threadFun2(LPVOID paramer)
{
DWORD threadID = (DWORD)paramer;
int i = 1;
while (true)
{
if (i <= 10)
PostThreadMessage(threadID, MY_MSG, i, NULL);
else
{
PostThreadMessage(threadID, WM_QUIT, NULL, NULL);
break;
}
i++;
Sleep(500);
}
return 0;
}
以上内容为学习笔记。