遭遇Windows消息循环

原创 2006年05月30日 23:34:00
今天跟同事联调一段代码,被一个问题郁闷了很久。

调用过程其实并不复杂,就是他提供一个Dll,并输出一个函数(姑且叫做Foo()吧),我调用他的函数Foo,其内部产生一个窗口。但是,我每次调用,窗口总是一闪而过!我们于是怀疑,是不是因为主程序是console,不支持MFC的缘故?要不然一定是因为不是在主线程里调用的缘故?!又是多线程,真是麻烦!

反复测试,结果如下

                 MFC对话框Win32      MFC Console
多线程             失败                         失败
单线程             成功                         失败

为什么?难道就不能在普通线程里创建窗口吗?什么是主线程(UI线程),什么又是工作线程?以前认为理所当然的事情,现在突然变得很模糊!

开始把目光锁定到消息队列上!是不是因为主线程有消息队列?比如MFC对话框程序就有消息队列,而Console没有。但是,同样是线程,为什么你有而我没有?难道是WinMain函数和普通的main函数不一样?到底消息队列是什么时候产生的?

草草浏览了CWinApp的代码,也没有找到答案。这时候,隐约想起了《Windows核心编程》里说的,系统在你第一次调用相关函数的时候,自动为线程创建消息队列!但是,到底是什么函数呢?

带着这个郁闷回到了家,打开那本Windows编程宝典,翻到消息队列一章。原来,每个窗口归属于创建它的线程。一旦线程退出,窗口也将自行销毁!另外,线程还要进行消息循环,以分发窗口的消息!注意,消息循环是由线程负责的!线程刚开始创建的时候是不带消息队列的,当线程第一次调用窗口相关的函数时,操作系统自动为其创建消息队列!原来,窗口的消息队列是归属于线程的!

问题终于搞清楚了,在普通的工作线程里,我们没有消息循环,所以创建出来的窗口还没有没有机会显示出来,线程就结束退出了!即使在console程序里,通过cin.get()让程序等待,窗口还是没有机会刷新(依赖消息循环分发并调用消息处理函数)而一直处于忙碌等待状态!而前面的Foo函数,恰恰要依赖于消息循环!

知道问题的真正原因后,就很容易解决了!在调用同事的函数产生窗口后(函数返回了),在同一个线程里进行消息循环!如下

...in a working thread...

Foo();   //call some function

while (GetMessage(&msg, NULL, 0, 0))
{
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

...working thread exit...

问题迎刃而解!你看不是MFC的问题,也不是不能在工作线程里创建窗口。本来,我一开始就怀疑,这么依赖MFC,总不能让主程序都是MFC程序吧!作为一个DLL组件,不能对调用者有太多的限制!而多线程,太寻常了,如果都在主线程里做,那也太难模块化了吧!当然了,现在说这些都是马后炮,当时郁闷的时候,什么古怪的理由都用上了!

其实,这个问题本来可以解决得更快点的。如果同事事先说明他的Foo函数何时返回(我一直以为它要一直阻塞到其产生的窗口关闭才返回的,结果并不是这样的,窗口一产生它就返回了),以及是否需要依赖外部的消息循环(他是有提过,但也很模糊,搞不清具体为什么)。当然,最大的原因还是因为大家对Windows的消息循环机制理解得不是很深入!

现在你搞明白Windows的消息循环到底是如何进行的了么?

关于windows程序的消息循环

一 消息循环 二 工作线程SendMessage 三: 关于消息响应中创建模态对话框阻塞线程消息循环的问题...
  • haithink
  • haithink
  • 2014年01月21日 11:29
  • 3506

Windows消息循环机制

 理解消息循环和整个消息传送机制对Windows编程来说非常重要。如果对消息处理的整个过程不了解,在windows编程中会遇到很多令人困惑的地方。 什么是消息(Message) 每个...
  • qq_25821067
  • qq_25821067
  • 2015年07月13日 17:25
  • 1390

Window之消息循环机制

简单介绍Windows消息循环机制,一个粗浅的认识。。。。 windows窗口的通用写法,设计窗口类(WNDCLASS),注册窗口类(RegisterClass),创建窗口(CreateWi...
  • halfIsNine
  • halfIsNine
  • 2016年08月10日 12:24
  • 508

windows下Django框架的搭建及测试教程

Django 框架搭建教程 一、Django简介 Django是一个开放源代码的Web应用框架,由Python写成。用了MVC的软件设计模式,即模型M,视图V和控制器C。 二、Django搭建步骤 ①...
  • u012249528
  • u012249528
  • 2014年12月09日 21:38
  • 1375

windows下安装rabbitmq的步骤详解

(仅作为个人的备忘记录) Rabbit MQ 是建立在强大的Erlang OTP平台上,因此安装Rabbit MQ的前提是安装Erlang。通过下面两个连接可以下载安装最新的版本: 下载并安装 E...
  • seven_coder
  • seven_coder
  • 2016年03月21日 14:58
  • 16381

在windows下使用Charles对移动终端抓包分析

从官网上下载Charles软件 Charles为收费软件,需破解,如果不注册只能使用30分钟,我在网上找到的破解方法:   安装以正常方式安装(下一步->下一步)即可   安装完以后...
  • liguilicsdn
  • liguilicsdn
  • 2016年04月21日 14:47
  • 14156

从Linux上访问Windows远程桌面

1.首先需要开启Windows上的远程桌面 打开控制面板 打开管理工具 打开服务并找到Terminal Services 确认Terminal Services...
  • hintcnuie
  • hintcnuie
  • 2013年07月08日 17:56
  • 21753

Windows中断处理

在现代操作系统当中,驱动并不是固定与中断相对应的,而是作为一种资源由程序员自己在驱动当中申请,这样在驱动加载之后,如果有中断产生的时候,就会调用在与中断相关的函数。...
  • dayenglish
  • dayenglish
  • 2014年08月01日 16:49
  • 1248

Windows环境下ELK平台的搭建

1.背景 日志主要包括系统日志、应用程序日志和安全日志。系统运维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性,从而及...
  • pilihaotian
  • pilihaotian
  • 2016年09月06日 17:31
  • 11232

FastDFS安装、配置、部署(一)-安装和部署

FastDFS是一个开源的,高性能的的分布式文件系统,他主要的功能包括:文件存储,同步和访问,设计基于高可用和负载均衡,FastDFS非常适用于基于文件服务的站点,例如图片分享和视频分享网站 Fas...
  • yiyihuazi
  • yiyihuazi
  • 2017年05月04日 14:08
  • 1930
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:遭遇Windows消息循环
举报原因:
原因补充:

(最多只允许输入30个字)