关于线程的封装

wuyapu 2009-01-16 09:29:09
大家可以看看

http://blog.csdn.net/wuyapu/archive/2009/01/16/3793566.aspx

希望大家踊跃讨论,我们共同提高
...全文
238 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wuyapu 2009-01-19
  • 打赏
  • 举报
回复

/**********************************************************************
* 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;
};


Eric011 2009-01-19
  • 打赏
  • 举报
回复
我是新手,看这些好深奥
mabo321 2009-01-19
  • 打赏
  • 举报
回复
学习……o(∩_∩)o...
wuyapu 2009-01-16
  • 打赏
  • 举报
回复
boost库里其实是对不同操作系统的线程包装成一个统一的接口了


jackzhhuang 说的有道理,但是我不原意为每个线程创建一个信号量
xiaoyisnail 2009-01-16
  • 打赏
  • 举报
回复
可以参考一下boost线程库的代码
waizqfor 2009-01-16
  • 打赏
  • 举报
回复
C++用模板来实现比较方便
http://www.cnblogs.com/phinecos/archive/2008/07/06/1236957.html这里写了一个线程封装类
大体思路都差不多
jackzhhuang 2009-01-16
  • 打赏
  • 举报
回复
我也封装过,看了一下你的代码,一个线程类可以生成nCount个线程,应该单独封装为好,即一个类只能生成一个线程。然后再进一步封装一个线程池类来生成多个线程。

此外,多线程可以考虑用线程池函数来管理。

还有等待线程结束的时候应该用信号量这样的方式实现。

一点点个人看法:)
sagegz 2009-01-16
  • 打赏
  • 举报
回复
UP!
lanmaozi 2009-01-16
  • 打赏
  • 举报
回复
感觉生成线程太多了
herman~~ 2009-01-16
  • 打赏
  • 举报
回复
mark

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧