1.UI线程

2.工作线程

把Delphi里TThread的WaitFor函数转化成C++代码,就会是下面这个样子。

  1. BOOL TThread::WaitFor(HANDLE hThread)
  2. {
  3. MSG msg;
  4. HANDLE handle[1];
  5. handle[0] = hThread;
  6. DWORD dwWaitResult = 0;
  7. do
  8. {
  9. // This prevents a potential deadlock if the background thread
  10. // does a SendMessage to the foreground thread
  11. if (dwWaitResult == WAIT_OBJECT_0 + 1)
  12. PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
  13. dwWaitResult = MsgWaitForMultipleObjects(1, handle, false, 1000, QS_SENDMESSAGE);
  14. if (dwWaitResult == WAIT_FAILED)
  15. return FALSE;
  16. if (dwWaitResult == WAIT_TIMEOUT)
  17. {
  18. TerminateThread(hThread, 0);
  19. return FALSE;
  20. }
  21. }
  22. while (dwWaitResult != WAIT_OBJECT_0);
  23. return TRUE;
  24. }

使我疑惑的是这两行代码

  1. if (dwWaitResult == WAIT_OBJECT_0 + 1)
  2. PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);

如果注释所讲是真的,那究竟在哪里处理了其它线程用SendMessage发送过来的消息呢?于是我翻MSDN,查PeekMessage函数,它有这样的解释:

“The PeekMessage function dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist).”

我用的是MSND2005,好像再早些的版本里并无“dispatches incoming sent messages”这句。光看这样的注释,实在是太晦涩了些。想起我原来好像发过个讨论这问题的帖子,翻了下发帖记录,还真有,见http://topic.csdn.net/u/20070824/14/d0c96e50-6348-49d3-98e4-9fcc9ead5fdd.html。我当时找到的答案是这样的:

“找到答案了。答案在<<Programming Applications for Microsoft Windows>>第26章的Waking a Thread一节.

The Algorithm for Extracting Messages from a Thread 's Queue
...

1. If the QS_SENDMESSAGE flag is turned on, the system sends the message to the   proper window procedure. Both the GetMessage and PeekMessage functions handle this processing internally and do not return to the thread after the window procedure has processed the message; instead, these functions sit and wait for another message to process.

我试着翻译一下:如果QS_SENDMESSAGE标志位有效,系统发送消息(即其它线程通过SendMessage发送过来的消息)到对应的窗口过程。GetMessage和PeekMessage函数在内部进行这样的处理,一直等到窗口过程处理完之后才会返回。也就是说,这些函数(GetMessage和PeekMessage)坐下来等到其它的消息处理完。”
   
书本里的解释已经很清楚详细了,我当时的译文有错误,原文是说GetMessage和PeekMessage调用窗口过程处理完SendMessage发送过来的消息后,还会继续坐下来等自己消息队列里的消息。

理论有了,结合着看看上面WaitFor的代码。MsgWaitForMultipleObjects的最后一个参数QS_SENDMESSAGE指明了如果其它有其它线程用SendMessage向本线程的窗口发送消息,MsgWaitForMultipleObjects就会立即返回,返回值为WAIT_OBJECT_0 + nCount(本例中nCount值为1),接下来就轮到PeekMessage登场了。

PeekMessage其实做了两件事,一件是把收到的消息标示为旧消息。见MSND里对MsgWaitForMultipleObjects返回值的解释:

“Functions such as PeekMessage, GetMessage, and WaitMessage mark messages in the queue as old messages.”

另一件就是把SendMessage发送过来的消息dispatch到窗口过程。下一次调用MsgWaitForMultipleObjects时队列里便没有新消息了。

那变旧的消息还在队列里吗?答案是不在。因为用SendMessage发送过来的消息根本就不会进应用程序的消息队列。在PeekMessage调用窗口过程处理完它时,它便消失了。而我们也很轻松的就知道,SendMessage函数把QS_SENDMESSAGE这个标志turn on了,PeekMessage和GetMessage还有WaitMessage把这个标志turn off了,把QS_SENDMESSAGE标志turn off的过程就是把消息变旧的过程。

PeekMessage究竟做了什么?的更多相关文章

  1. 异步编程系列第05章 Await究竟做了什么?

    p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...

  2. 一个请求中,ADF、JSF究竟做了哪些工作

    在Oracle ADF开发中,一个请求发生后,经过ADF处理后,我们可以很快得到响应页面,但在请求过程中ADF框架在背后究竟做了什么东西呢?今天让我们一起来了解下,ADF.JSF是基于组件模型的,不同 ...

  3. [源码解析] Flink的groupBy和reduce究竟做了什么

    [源码解析] Flink的groupBy和reduce究竟做了什么 目录 [源码解析] Flink的groupBy和reduce究竟做了什么 0x00 摘要 0x01 问题和概括 1.1 问题 1.2 ...

  4. 《大话数据库》-SQL语句执行时,底层究竟做了什么小动作?

    <大话数据库>-SQL语句执行时,底层究竟做了什么小动作? 前言 大家好,我是Taoye,试图用玩世不恭过的态度对待生活的Coder. 现如今我们已然进入了大数据时代,无论是业内还是业外的 ...

  5. 当我们按下电源键,Android 究竟做了些什么?

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由goo发表于云+社区专栏 相信我们对Android系统都不陌生,而Android系统博大精深,被各种各样的智能设备承载的同时,我们会否 ...

  6. UdpClient的Connect究竟做了什么(转)

    最近在写一个音频通信的系统,因为需要还要处理其他事件,所以就自己设计底层的通信协议,用了不少底层的Socket编程(.Net Framework),搞清楚了不少细节问题. 先做一些铺垫工作.音频系统服 ...

  7. 一张图带你看懂SpriteKit中Update Loop究竟做了神马!

    1首先Scene中只有开始一点时间用来回调其中的update方法 ;] 2然后是Scene中所有动作的模拟 3接下来是上一步完成之后,给你一个机会执行一些代码 4然后是Scene模拟其中的物理世界 5 ...

  8. select count(*) 底层究竟做了什么?

    阅读本文大概需要 6.6 分钟. SELECT COUNT( * ) FROM t是个再常见不过的 SQL 需求了.在 MySQL 的使用规范中,我们一般使用事务引擎 InnoDB 作为(一般业务)表 ...

  9. 为什么 java wait/notify 必须与 synchronized 一起使用,jvm究竟做了些什么

    这个课题提出来的是原先的线程并发解决的思路.目前解决线程并发,可以是lock接口结合condition  并发问题一直以来就是线程必不可少的话题. java 是第一个内置对多线程支持的主流编程语言.在 ...

随机推荐

  1. ASP.NET MVC生成静态页面

    1.先付上封装好生成静态页的原代码: public class Common { #region 获取模板页的Html代码 /// <summary> /// 获取页面的Html代码 // ...

  2. Codeforces 912E Prime Gift(预处理 + 双指针 + 二分答案)

    题目链接 Prime Gift 题意  给定一个素数集合,求第k小的数,满足这个数的所有质因子集合为给定的集合的子集. 保证答案不超过$10^{18}$ 考虑二分答案. 根据折半的思想,首先我们把这个 ...

  3. 2016集训测试赛(十九)Problem C: 无聊的字符串

    Solution 傻X题 我的方法是建立后缀后缀树, 然后在DFS序列上直接二分即可. 关键在于如何得到后缀树上每个字符对应的字节点: 我们要在后缀自动机上记录每个点在后缀树上对应的字母. 考虑如何实 ...

  4. 解决vagrant不能正常挂载目录的问题

    解决方案: vagrant plugin install vagrant-vbguest

  5. VS2010 MFC中 窗口分割的实现

    分割窗口概述 分割窗口,顾名思义,就是将一个窗口分割成多个窗格,在每个窗格中都包含有视图,或者是同一类型的视图,或者是不同类型的视图. MFC分割窗口的方式有两种,动态分割和静态分割. 动态分割窗口通 ...

  6. 【GLSL教程】(八)纹理贴图 【转】

    http://blog.csdn.net/racehorse/article/details/6664717 简单的纹理贴图(Simple Texture) 为了在GLSL中应用纹理,我们需要访问每个 ...

  7. 在windows搭建jenkins測试环境

    jenkins 搭建好开发环境必备之中的一个,简单易用,搭建測试平台非常有帮助,不知道的都能够了解一下 官网下载地址 http://jenkins-ci.org/ 我是下载window版本号的 安装有 ...

  8. Direct-X学习笔记--纹理映射

    一.介绍 之前学习了如何绘制物体,还画了个DX自带的茶壶,然而这个东东并不怎么好看....离我们现实的物体简直相隔千里. 仅仅能说像美术他们用来写生的模型...那么要怎么样才干让我们的东西看起来更像真 ...

  9. css:清除浮动 overflow

    是因为overflow除了(visible)会重新给他里面的元素建立块级格式化(block formatting context)floats, position absolute, inline-b ...

  10. UTF-8 可变编码格式

    转自:http://blog.csdn.net/swedenfeng/article/details/53467720   UTF-8 是一种可变编码格式,长度从一个字节到四个字节,可根据UTF-8字 ...