日期:2014-05-16  浏览次数:20752 次

windows消息机制的有趣发现(一)

最近琢磨windows的消息机制,发现一些有趣的地方,可能是对的,也可能是错的,分享出来让大家评判评判。

1:每个线程都有消息队列

不仅仅是有窗口的线程,没有窗口的线程也有消息队列!编写一个win32控制台程序,代码如下:

#include<windows.h>

void main()
{   
	DWORD dwThread = GetCurrentThreadId();
	::PostThreadMessage(dwThread,10000,NULL,NULL);
	MSG msg;
	GetMessage(&msg,NULL,NULL,NULL);
}

 

获取当前线程ID,对当前线程发送线程消息,然后调用GetMessage函数从消息队列中取消息,看看能不能取到我们之前发出的编号为10000的消息。

运行发现GetMessage函数成功从消息队列中取出了我们发送的编号为10000的消息!我们这个线程没有窗口、没有消息循环,但是有消息队列,消息队列是windows为线程提供的。

2:消息队列的容量有多大?

如果我们不停的发送消息,却不用GetMessage之类的函数获取并从消息队列中移除消息。消息队列中的消息岂不是越来越多?那么这个消息队列究竟有多大容量呢?它最多能容纳多少消息?我们编写如下代码

#include<windows.h>

void main()
{   
	DWORD dwThread = GetCurrentThreadId();
	for (int i=0;i<1000;i++)
	PostThreadMessage(dwThread,10000,NULL,NULL);
	int n = 0;
	MSG msg;
	while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
	{
		if (msg.message == 10000)
			n++;
	}

}

循环调用PostThreadMessage发送1000个消息,然后用PeekMessage取出消息,最后一个参数PM_REMOVE说明每取出一个消息后将该消息从消息队列中移除。我们用变量n来统计从消息队列中取出了多少个编号为10000的消息。这里为什么不用GetMessage呢?因为GetMessage把消息队列中的消息取完了以后会阻塞起来一直等待,我们的while循环无法退出,后面的断点也无法命中。而PeekMessage把消息队列中的消息取完了以后,取不到消息就返回0,我们的while也就结束了。

运行后发现,果然,n的值为1000,取出了1000个我们发送的消息。接下来我们再增大消息的发送数量,看看还能取出多少。

这次我们发送了50000个消息,但是运行后发现只从消息队列中取出了10000个消息!消息队列的容量为10000个吗?我们上网查资料,确实如此。消息队列的容量默认为10000个,这个值可以在注册表中修改。

展开注册表:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\

找到USERPostMessageLimit 项,发现该项的默认值为10000。我们可以通过修改该值来改变消息队列的容量,重启后生效。