线程包装方法

最近闲来无事,在思考如何包装线程,方便调用,下面是我的代码,希望大家多提建议

这样就很方便的将一个类的某个成员函数包装成线程进行执行了

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值