王朝百科
分享
 
 
 

CWinThread

王朝百科·作者佚名  2010-04-26  
宽屏版  字体: |||超大  

Windows以消息驱动方式工作,每个WIN32应用程序都至少包含一个消息队列和一个消息泵。消息队列建立在操作系统提供内存保留区中,消息泵不断搜寻消息队列,将取得的消息分发给应用程序的各个部分进行处理,这个过程叫做消息循环。基本消息循环如下:

//从队列中提取消息

while(GetMessage(&msg,0,0,0))

{

//转换消息参数

TranslateMesssage(&msg);

//分发消息

DispatchMessage(&msg);

}

Windows以线程封装消息循环,封装消息循环的线程叫做用户界面线程,即UI线程。该线程可以创建并撤销窗口。此外,还有一种线程叫做工作者线程,它是辅助UI线程工作的,它没有消息循环,不能处理系统事件和窗口消息,也不能关联主窗口。主线程和辅线程虽然享有共同的虚拟地址空间,但各自占用独立的CPU时间片,参与系统资源的竞争。所以,可以使用辅线程完成经常性的、耗费机时的数据处理工作(例如网络通信),减轻UI线程的负担,确保UI线程及时响应用户的窗口操作。根据需要,一个应用程序中也可以创建多个UI线程。

CWinThread类是MFC用来封装线程的,包括UI线程和工作者线程。因此每个MFC程序至少使用一个CWinThread派生类。被MFC程序员熟知的CWinApp应用类就从这里派生。

下面介绍几个实用的CWinThread类成员函数。

虚函数InitInstance

Windows允许同时运行一个应用程序的多个备份,又称为运行一个程序的多个实例。InitInstance就是“初始化实例”的意思,可见,它是在实例创建时首先被调用的。应用程序总要重载这个虚函数,进行系统设置,创建运行环境。例如,主窗口一定要在InitInstance()中创建,因为该函数退出后就进入该线程的消息循环。

虚函数Run

该函数提供UI线程的消息循环,即反复地提取消息,分发消息,直到收到WM_QUIT退出循环,线程随即结束。在循环中,如果当前没有收到消息,则调用空闲消息处理程序OnIdle() 。以下是该函数的完整定义。

virtual int CWinThread::Run()

{

ASSERT_VALID(this);

//是否要做空闲处理

BOOL bIdle = TRUE;

//用户记录空闲处理已经连接执行的次数

LONG lIdleCount = 0;

//acquire and dispatch messages until a WM_QUIT message is received.

//消息循环

for (;;)

{

//如果空闲状态为真,且消息队列为空,则进行空闲处理

while(bIdle && !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))

{

//PeekMessage()用于检查消息队列是否为空,但并不处理消息

//调用空闲处理程序,如果返回零,说明空闲处理已全部完成

if (!OnIdle(lIdleCount++))

bIdle = FALSE;

}

//空闲处理循环结束,进入消息泵循环

do

{

//调用消息泵,提取消息并分发消息

//如果收到WM_QUIT消息,则退出消息循环

if (!PumpMessage())

return ExitInstance();

//根据刚处理的消息类型,判断是否应该在没有消息到来时立即进行空闲处理

if (IsIdleMessage(&m_msgCur))

{

bIdle = TRUE;

//在重新进行空闲处理前,清空空闲处理的执行次数

lIdleCount = 0;

}

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));

}

ASSERT(FALSE); //不可能执行的语句

}

/*------------- 消息泵函数PumpMessage() ----------------*/

//省略了调试信息的输出功能

BOOL CWinThread::PumpMessage()

{

ASSERT_VALID(this);

//取出消息队列中的第一个消息,直到取得消息,该函数才返回

if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))

{

//收到WM_QUIT消息

return FALSE;

}

//处理消息,但不处理WM_KICKIDLE

if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))

{

//转换虚键消息到字符消息

::TranslateMessage(&m_msgCur);

//分发消息

::DispatchMessage(&m_msgCur);

}

return TRUE;

}

阅读PumpMessage代码可知,消息泵并不处理WM_KICKIDLE消息,收到该消息后,直接返回。其实,WM_KICKIDLE消息被用来刺激空闲处理的执行,它作为一个空消息促使::GetMessage()返回。

虽然Run()是虚拟函数,但很少被重载。

虚函数ExitInstance

与InitInstance()相反,该函数是在退出消息循环时执行,一般被框架调用,做最后的清理工作。但如果调用InitInstance()失败,ExitInstance()也会被调用。可以重载ExitInstance(),为线程做相关的清理工作。不要在除重载的Run()函数外的地方调用它。如果将CWinThread成员变量m_bAutoDelete设为TRUE,CWinThread::ExitInstance()会删除当前的CWinThread对象。所以,如果在堆栈中构造了UI线程对象,可以利用默认的ExitInstance()自动将它删除。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
中国古代四大美女:背后隐藏惊人秘密
 女性   2025-06-20
如何用java替换看不见的字符比如零宽空格​十六进制U+200B
 干货   2023-09-10
网页字号不能单数吗,网页字体大小为什么一般都是偶数
 干货   2023-09-06
java.lang.ArrayIndexOutOfBoundsException: 4096
 干货   2023-09-06
Noto Sans CJK SC字体下载地址
 干货   2023-08-30
window.navigator和navigator的区别是什么?
 干货   2023-08-23
js获取referer、useragent、浏览器语言
 干货   2023-08-23
oscache遇到404时会不会缓存?
 干货   2023-08-23
linux下用rm -rf *删除大量文件太慢怎么解决?
 干货   2023-08-08
刀郎新歌破世界纪录!
 娱乐   2023-08-01
js实现放大缩小页面
 干货   2023-07-31
生成式人工智能服务管理暂行办法
 百态   2023-07-31
英语学习:过去完成时The Past Perfect Tense举例说明
 干货   2023-07-31
Mysql常用sql命令语句整理
 干货   2023-07-30
科学家复活了46000年前的虫子
 探索   2023-07-29
英语学习:过去进行时The Past Continuous Tense举例说明
 干货   2023-07-28
meta name="applicable-device"告知页面适合哪种终端设备:PC端、移动端还是自适应
 干货   2023-07-28
只用css如何实现打字机特效?
 百态   2023-07-15
css怎么实现上下滚动
 干货   2023-06-28
canvas怎么画一个三角形?
 干货   2023-06-28
canvas怎么画一个椭圆形?
 干货   2023-06-28
canvas怎么画一个圆形?
 干货   2023-06-28
canvas怎么画一个正方形?
 干货   2023-06-28
中国河南省郑州市金水区蜘蛛爬虫ip大全
 干货   2023-06-22
javascript简易动态时间代码
 干货   2023-06-20
 
>>返回首页<<
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有