一.在MFC中创建一个用户界面线程
1.从CWinThread派生一个线程类CMyThread
重载CMyThread的InitInstance(),ExitInstance()
BOOL CMyThread::InitInstance()
{
// Do what you want to do
PostThreadMessage(WM_QUIT,0,0);
return TRUE;
}
int CMyThread::ExitInstance()
{
//do what you want to do
return CWinThread::EixtInstance();
}
2.在要调用的类里头文件
定义
CMyThread* pThread;
要起线程的时候
pThread->CreateThread();
在CWinThread中的m_pMainWnd存放线程主窗口的对象指针,一般在InitInstance()
中赋值,当它所指向的窗口被关闭时,MFC类库将自动终止你的线程.
如:
定义全局变量
CMyDialog* pDlg;
在重载线程的InitInstance()时候设置该值,
pDlg = New CMyDialog;
this->m_pMainWnd = pDlg;
成员变量m_pActiveWnd存放活跃窗口对象指针,当一个OLE服务器活跃时它指向容器
应用程序主窗口,其他特性和m_pMainWnd几乎一样.
CWinThread类的成员函数GetMainWnd获得线程的主窗口,virtual CWnd*
GetMainWnd();该函数考虑了应用程序是OLE服务器的情况,所以调用它来获取主窗
口指针,这样无须考虑这个问题了,通过这个窗口指针,线程可以进行一些所需要的
工作,另外,在线程内部,自己定义窗口指针,实现对一个自定义窗口的控制.
二.用MFC创建一个工作者线程
1.创建工作者线程
工作者线程通常用于进行程序的后台任务,如计算、调度等工作。它不需要从CWinT
hread类派生创建.最重要的是实现完成工作者线程任务的运行控制函数.该函数的
入口点是线程的启动点,函数最后执行结束,线程就终止了.控制函数的基本结构:
UINT ControllingFunction(LPVOID pParam)
{
...
//工作者线程所需要完成的任务
...
}
当函数终止时,返回一个UNIT值,指明终止的原因.一般用0来表示成功,其他值表明
错误原因,调用者可以使用GetExitCodeThred来获取这个返回值.
2.启动工作者线程
调用AfxBeginThread()函数来启动工作者线程,其创建和初始化CWinThread对象,使
用控制函数来启动线程,并返回CWinThread对象指针.
如建立一个显示广告图片的工作线程:
定义
static UINT LoadAds(LPVOID pParam);
UINT CMyApp::LoadAds(LPVOID pParam)
{
....
return 0;
}
启动工作者线程
AfxBeginThread(LoadAds,this,THREAD_PRIORITY_LOWEST);
CreateThread是系统调用
_beginthread是C运行时库API,_beginthread可移植性好一些
3.线程终止
对于工作者线程,控制函数结束表明线程结束,或者调用AfxEndThread(UINT
nExitCode).只用于线程内部终止时调用.
对于用户界面线程,可以任意处调用PostQuitMessage(int nExitCode)结束线程.
//PostThreadMessage()
异常终止 TerminateThread(); //很危险的函数,如果被终止的线程拥有临界区,它
将不被释放,和CloseHandle函数结合起来使用,从安全性和程序的健壮性来讲,还是
可以的.
三.线程的管理和操作
通过int GetThreadPriority()获取线程的优先权,BOOL SetThreadPriority()来
设置线程的优先级。
DWORD ResumeThread,DWORD SuspendThread来完成继续执行和挂起线程。
四.线程间的通讯
1.使用同步类控制访问共享数据
2.使用消息队列,使用CWinThread::PostThreadMessage()向某个线程发消息
五.线程的同步
同步对象CSyncObject,CSemaphore,CMutex,CCriticalSection和CEvent
同步访问对象CMultiLock,CSingleLock
使用这些对象时候,需要把头文件Afxmt.h加入到程序中,#include <afxmt.h>
1.同步对象
CSyncObject是一个抽象类,封装了Win32中最基本的同步对象功能,提供了Lock和Unlock等基本函数。
在应用程序访问资源之前必须等待某事件的发生,例如,数据通讯中将数据写入文件之前等待数据通讯端口送来的数据,可以使用事件CEvent类.
当一个应用程序中的多个线程要访问资源,例如在同样的文档之上可以影射多个视窗时,用信号量CSemaphore类控制,使用互斥量CMutex类可以控制多个应用程序访问资源,尤其是在资源DLL中的情况.此外还可以使用临界区CCriticalSection类来控制一段代码执行.
如:
定义一个CSemaphore* m_regSem;
m_regSem.Lock();
m_regSem.UnLock();来设置同步控制标志.
2.同步访问对象
如果一次仅等待一个同步对象,则使用CSingleLock类.
在某个特定时刻要使用多个同步对象,则使用CMutiLock类