日期:2014-05-16 浏览次数:20736 次
最近琢磨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。我们可以通过修改该值来改变消息队列的容量,重启后生效。