今天详细研究了下CreateThread()函数创建线程,并将其包装使用的方法,现在给大家讲解下:
MyThread.h //头文件
class MyThread;
class ThreadCallback{ //线程回调类
public:
virtual BOOL Run(MyThread* pCurThread)=0;
};
class MyThread{
public:
void Init(ThreadCallback*pi ){return m_pi = pi;}
MyThread();
//析构函数
//.....
BOOL Start(); //线程对象调用,创建线程
private:
ThreadCallback* m_pi;
private:
static DWORD WINAPI ThreadProc(LPVOID lpParam); //线程函数
};
MyThread .cpp //实现类
MyThread::MyThread(){....} //初始化成员变量
BOOL MyThread::Start(){ //start函数
...
//外部在用MyThead对象调用Start()后便创建了线程
m_hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,this,0,(LPDWORD)&m_nThreadID);
}
DWORD WINAPI MyThread::ThreadProc(LPVOID lpParam){
MyThread* pthis = (MyThread*)lpParam;
ASSERT(pthis&& pthis ->m_pi);
BOOL bRun = pthis->m_pi->Run(pthis);//对象传入线程运行函数中,可以调用此对象结果中的其他成员
CloseHandle(pThis->m_nThread);//线程退出时关闭
。。。。
}
我想说的其实这是一种很高明的做法,首先我们定义的MyThread类其实就是一个封装了很多信息的类,其中有很多有用信息,比如说我可以定义控制线程退出的变量,线程句柄,线程ID,线程状态变量为此结构的成员变量,这样就可以很自然的监控线程状态。
以下在看看此创建的线程是如何被调用的
Cutter.h
classCutter:public ThreadCallback{ //继承线程回调
public:
Cutter(); //构造函数
proctected:
virtual BOOL Run(MyThread*pCurThread);//线程回调覆盖
private:
MyThread mThread;
};
Cutter.cpp
Cutter::Cutter(){ //构造
mThread.Init(this); //这个初始化调用的是MyThead类中的,初始化了MyThread对象中的m_pi;
}
以上是相关的代码:
在Cutter.cpp中需要启动线程的地方这样调用 mThread.Start() ;
分析下过程吧:Start()===>CreatThread()===>ThreadProc()===>myThread->m_pi->Run(myThread);
就是这样的。这里调用的Run是Cutter里的,因为将基类中的Run给覆盖了,呵呵,其实还可以继续封装,凭个人的方法吧。