CWinThread类是MFC用来
封装线程的,包括UI线程和工作者线程。
因此每个MFC程序至少使用一个CWinThread派生类。被MFC程序员熟知的CWinApp应用类就从这里派生。
Windows以消息驱动方式工作,每个WIN32应用程序都至少包含一个
消息队列和一个消息泵。
消息队列建立在操作系统提供内存保留区中,消息泵不断搜寻消息队列,将取得的消息分发给应用程序的各个部分进行处理,这个过程叫做
消息循环。基本
消息循环如下:
//从
队列中获取消息
while(GetMessage(&msg,0,0,0))
{
//转换消息参数
TranslateMesssage(&msg);
//分发消息
DispatchMessage(&msg);
}
Windows以线程封装
消息循环,封装消息循环的线程叫做用户界面线程,即
UI线程。该
线程可以创建并撤销窗口。此外,还有一种线程叫做
工作者线程,它是辅助UI线程工作的,它没有
消息循环,不能处理系统事件和窗口消息,也不能关联主窗口。
主线程和辅线程虽然享有共同的
虚拟地址空间,但各自占用独立的CPU时间片,参与系统资源的竞争。所以,可以使用辅线程完成经常性的、耗费机时的数据处理工作(例如网络通信),减轻UI线程的负担,确保UI线程及时响应用户的窗口操作。根据需要,一个应用程序中也可以创建多个UI线程。
下面介绍几个实用的CWinThread类成员函数。
虚函数InitInstance
Windows允许同时运行一个应用程序的多个备份,又称为运行一个程序的多个实例。InitInstance就是“初始化实例”的意思,可见,它是在实例创建时首先被调用的。应用程序总要
重载这个
虚函数,进行
系统设置,创建运行环境。例如,主窗口一定要在InitInstance()中创建,因为该函数退出后就进入该线程的
消息循环。
虚函数Run
该函数提供UI线程的
消息循环,即反复地提取消息,分发消息,直到收到WM_QUIT退出循环,线程随即结束。在循环中,如果当前没有收到消息,则调用空闲消息处理程序OnIdle() 。以下是该函数的完整定义。
//RUN 函数调用消息幚PumpMessage 循环处理消息。
阅读PumpMessage代码可知,消息泵并不处理WM_KICKIDLE消息,收到该消息后,直接返回。其实,WM_KICKIDLE消息被用来刺激空闲处理的执行,它作为一个空消息促使::GetMessage()返回。
虚函数ExitInstance
与InitInstance()相反,该函数是在
退出
消息循环时执行,一般被
框架调用,做最后的清理工作。但如果调用InitInstance()失败,ExitInstance()也会被调用。可以
重载ExitInstance(),为线程做相关的清理工作。不要在除
重载的Run()函数外的地方调用它。如果将CWinThread
成员变量m_bAutoDelete设为TRUE,CWinThread::ExitInstance()会删除当前的CWinThread对象。所以,如果在
堆栈中构造了UI线程对象,可以利用默认的ExitInstance()自动将它删除。
CWinThread的使用
常见的启动线程函数有三个:
CreateThread(), _beginThread(以及_beginThreadEx()),AfxBeginThread()
1和2是sdk函数,3是mfc函数
至于启动的是工作者线程还是UI线程,是由函数3的参数来决定的 ;
一个例子:
请注意以下两点:
1.在UIThreadDlg.cpp的开头加入语句: #include "UIThread.h"
2.把UIThread.h中类CUIThread()的构造函数的特性由 protected 改为 public。
用户界面线程的执行次序与应用程序主线程相同,首先调用用户界面线程类的InitInstance()函数,如果返回TRUE,继续调用线程的 Run()函数,该函数的作用是运行一个标准的消息循环,并且当收到WM_QUIT消息后中断,在消息循环过程中,Run()函数检测到线程空闲时(没有消息),也将调用OnIdle()函数,最后Run()函数返回,MFC调用ExitInstance()函数清理资源。
你可以创建一个没有界面而有消息循环的线程,例如:你可以从CWinThread派生一个新类,在InitInstance函数中完成某项任务并返回FALSE,这表示仅执行InitInstance函数中的任务而不执行消息循环,你可以通过这种方法,完成一个工作者线程的功能。
另一个例子:
- //.h 文件
- #define WM_TEST WM_USER + 1
- class CTestThread : public CWinThread
- {
- DECLARE_DYNCREATE(CTestThread)
- protected:
- CTestThread ();
- virtual ~CTestThread ();
- public:
- virtual BOOL InitInstance();
- virtual int ExitInstance();
- protected:
- afx_msg void OnTest(WPARAM wParam,LPARAM lParam);
- DECLARE_MESSAGE_MAP()
- };
- //.Cpp 文件
- #include "stdafx.h"
- #include "TestThread.h"
- IMPLEMENT_DYNCREATE(CTestThread, CWinThread)
- CTestThread::CTestThread()
- {
- }
- CTestThread::~CTestThread()
- {
- }
- BEGIN_MESSAGE_MAP(CTestThread, CWinThread)
- ON_THREAD_MESSAGE(WM_TEST,OnTest)
- END_MESSAGE_MAP()
- BOOL CTestThread::InitInstance()
- {
- return TRUE;
- }
- int CTestThread::ExitInstance()
- {
- return CWinThread::ExitInstance();
- }
- void CTestThread::OnTest(WPARAM wParam,LPARAM lParam)
- {
- AfxMessageBox("test");
- }
- //调用的地方
- CWinThread* m_pThrd;
- //启动
- m_pThrd = AfxBeginThread(RUNTIME_CLASS(CTestThread));
- // 需要执行线程中的操作时
- m_pThrd->PostThreadMessage(WM_TEST,NULL,NULL);
- // 结束线程
- HANDLE hp=m_pThrd->m_hThread;
- if (hp)
- {
- if (WaitForSingleObject(hp, 1) != WAIT_OBJECT_0)
- {
- TerminateThread(hp,0);
- }
- CloseHandle(hp);
- }