64,647
社区成员
发帖
与我相关
我的任务
分享
/**********************************************************************
* CThreadBase
* 该类用来将某个对象的某个成员函数包装成线程函数
* 方便线程调用
* 类的成员函数格式要求 unsigned long T::(bool&,ARG)
* T 要包装的对象类型
* ARG 成员函数的参数类型
**********************************************************************/
template<typename T,typename ARG>
class CThreadBase
{
public:
typedef unsigned long (T::*THREADFUNC)(bool&,ARG);
//该类是线程辅助类,存储线程的一些基本信息
class CThreadInfo
{
public:
CThreadInfo()
{
m_pFunc = NULL;
m_pObj = NULL;
m_pThis = NULL;
m_bStart = true;
m_hThread = NULL;
m_bStopped = false;
}
~CThreadInfo()
{
}
CThreadInfo(CThreadBase<T,ARG>* pThis,T* pObj,THREADFUNC func,ARG arg)
{
m_pFunc = func;
m_pObj = pObj;
m_pThis = pThis;
m_Arg = arg;
m_bStart = true;
m_hThread = NULL;
m_bStopped = false;
}
bool m_bStart;
bool m_bStopped;
THREADFUNC m_pFunc;
T* m_pObj;
ARG m_Arg;
CThreadBase<T,ARG>* m_pThis;
HANDLE m_hThread;
};
CThreadBase()
{
}
//该类析构时会退出所有的线程
virtual ~CThreadBase()
{
StopThread(NULL,NULL);
}
/************************************************************
* 启动线程
* T* pObj 对象
* THREADFUNC func 对象成员函数的指针
* ARG arg 函数的参数
* int iCount 指定启动相同的线程的数量
* int iPriority 指定线程的优先级
* 返回值 启动的线程的数量
************************************************************/
int StartThread(T* pObj,THREADFUNC func,ARG arg,int iCount=1,
int iPriority=0)
{
int iRet = 0;
HANDLE hThread = NULL;
unsigned int dwID;
CThreadInfo* pInfo = NULL;
for(int i=0;i<iCount;i++)
{
pInfo = new CThreadInfo(this,pObj,func,arg);
//hThread = CreateThread(NULL,0,ThreadProc,pInfo,CREATE_SUSPENDED,&dwID);
hThread = (HANDLE)_beginthreadex(NULL,0,ThreadProc,pInfo,CREATE_SUSPENDED,&dwID);
if(hThread==NULL)
{
delete pInfo;
continue;
}
pInfo->m_hThread = hThread;
iRet++;
//此处应该使用临界区
m_Critical.Enter();
m_Threads.push_back(pInfo);
m_Critical.Leave();
//允许线程开始运行
ResumeThread(hThread);
SetThreadPriority(hThread,iPriority);
}
return iRet;
}
/*****************************************************************
* 停止指定线程
* T* pObj 对象指针,如果该值为NULL,说明停止所有的线程
* THREADFUNC func 对象成员函数的指针
* 返回值 正确停止的数量
******************************************************************/
int StopThread(T* pObj,THREADFUNC func)
{
int iRet = 0;
std::list<CThreadInfo*>::iterator it;
CThreadInfo* pInfo;
//此处应该使用临界区
CSingleLock<CCriticalSection> lock(&m_Critical);
it = m_Threads.begin();
//for(it=m_Threads.begin();it!=m_Threads.end();it++)
while (it!=m_Threads.end())
{
pInfo = *it;
if(NULL==pObj || (pInfo->m_pObj == pObj && pInfo->m_pFunc == func))
{
pInfo->m_bStart = false; //给线程信号,让线程自己退出
//等待线程结束
while(!pInfo->m_bStopped)
{
Sleep(10);
}
it = m_Threads.erase(it);
delete pInfo;
}
else
{
it++;
}
}
return iRet;
}
protected:
std::list<CThreadInfo*> m_Threads; //存储当前运行的线程的信息
CCriticalSection m_Critical;
private:
static unsigned int WINAPI ThreadProc(void* pParam)
{
unsigned long dwRet;
std::list<CThreadInfo*>::iterator it;
CThreadInfo* pInfo = (CThreadInfo*)pParam;
CThreadBase<T,ARG>* pThis = pInfo->m_pThis;
dwRet = (pInfo->m_pObj->*(pInfo->m_pFunc))(pInfo->m_bStart,pInfo->m_Arg);
pInfo->m_bStopped = true;
//此处应该使用临界区
CSingleLock<CCriticalSection> lock(&pThis->m_Critical);
//说明是线程自动退出,不是StopThread引起的
if(pInfo->m_bStart)
{
//从线程列表中删除这个对象
it = std::find(pThis->m_Threads.begin(),
pThis->m_Threads.end(),pInfo);
if(it!=pThis->m_Threads.end())
{
pThis->m_Threads.erase(it);
delete pInfo;
}
}
return dwRet;
}
};
下面是如何使用该类
class CTest
{
public:
CTest()
{
}
DWORD Thread(bool& bStart,int i)
{
//std::cout<<"Thread Started!\n";
while(bStart)
{
m_Critical.Enter();
//std::cout<<"CTest::Thread " <<i++<<" OK!"<<std::endl;
m_Critical.Leave();
Sleep(10);
}
//std::cout<<"Thread Stopped!\n";
return 100;
}
DWORD Thread2(bool& bStart,int i)
{
std::cout<<"Thread Started!\n";
while(bStart)
{
m_Critical.Enter();
std::cout<<"CTest::Thread TWO " <<i++<<" OK!"<<std::endl;
m_Critical.Leave();
Sleep(1000);
}
std::cout<<"Thread Stopped!\n";
return 100;
}
int Start()
{
m_Thread.StartThread(this,&CTest::Thread,10,2000);
return m_Thread.StartThread(this,&CTest::Thread2,10,1);
}
void Stop()
{
m_Thread.StopThread(this,&CTest::Thread);
m_Thread.StopThread(this,&CTest::Thread2);
}
private:
CThreadBase<CTest,int> m_Thread;
CCriticalSection m_Critical;
};