程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 如何讓程序自動管理線程

如何讓程序自動管理線程

編輯:關於VC++

引言

多線程是一種很好的程序機制,使用線程可以充分的利用電腦資 源,進行並行的業務處理。不過好的東西總有它的不足。線程是好,不過濫用, 或管理不當就會造成線程混亂,內存漏洞,造成電腦速度變慢,反應遲鈍。

想法

於是有人提出能不能讓線程自己管理自己,把這復雜的工作 交給電腦來處理。筆者經過多年的實踐,終於用VC++實現了這一目的。

大家知道在VC++中我們可以用CreateThread創建一個線程,該函數返回這線程 的Handle,以後我們就可以用這個Handle來管理這個線程的。於是我們可以做一 個類名為ThreadManager,來管理這些Handle,並隨時監控這些線程的狀態。

總的思想就是這樣,不過為了方便使用,我們最好把這個類封裝成DLL的 形式,這樣以後我們在任何程序中都可以很方便的用該類來管理線程了(當然如果 你有興趣,也可以用COM模型來實現)。

實現

因為我們要把一切工 作全交給ThreadManager,所以線程的創建,監控,刪除都將在該類中實現,而我 們僅要做的就是把線程函數名和線程參數傳給ThreadManager類,於是我們定義該 類構造函數為:

ThreadManager(ThreadPrc threadpro,LPVOID pParam);

該類還要能啟動線程,於是我們又定義一個啟動函數:

RunThread();

另外我們有時還要能獲得線程的Handle,於 是又定義一個函數:

HANDLE GetThreadHandle();

而該類唯 一的成員參數就是Handle:

HANDLE m_Handle;

於是 ThreadManager定義如下:

typedef DWORD (WINAPI *ThreadPro) (LPVOID);
class CThreadManager : public CObject
{
   DECLARE_DYNAMIC( CThreadManager ) 
public:
   CThreadManager( ThreadPrc threadpro, LPVOID pParam);
   ~CThreadManager();
  CBOOL RunThread();
  HANDLE GetThreadHandle() const { return( m_Handle ); };
private:
   HANDLE m_Handle;
};

顯然,我們僅有這一個類還不能完成我 們所需的工作,我們還要一個負責具體監控的ThreadTask類,ThreadTask類中有 一個監控線程ThreadTaskFunc( )負責監控並刪除線程。該類定義如下:

class CThreadTask : public CObject
{
DECLARE_DYNAMIC( CThreadTask )
public:
  CThreadTask();   //構造函數
  ~CThreadTask();
  CBOOL IsValid();
   void AddHandle( CONST HANDLE cHandle ); //添加線程句柄到m_ObList中

  void CloseThreadHandles();  //(關閉線程)
   static CThreadTask& GetCThreadTask();  //用於在Managerthread類中 獲得ThreadTask類的指針
  CObList  m_ObList;//線程句柄組
  HANDLE m_Handle;//線程句柄

  BOOL m_bKeepGoing;//是否 已運行
};
IMPLEMENT_DYNAMIC( CThreadCareTaker, CObject )

其中IsValid()是用於檢驗ThreadTaskFunc()是否已動行了,其它意思 都很明顯。 

流程圖

總的流程圖如下:

具體 實現

下面給出它的具體實現。

ThreadTask::ThreadTask()
{
 m_bKeepGoing = TRUE;
 //表示已運行
 DWORD nThreadId = 0;
 //創建管理線程
 m_Handle = (HANDLE)::CreateThread(NULL,0,ThreadTaskpro,0,0,&nThreadId );
}
void ThreadTask::AddHandle( CONST HANDLE cHandle )
{
  CHandle *pHandle = new CHandle;
  pHandle- >m_ThreadHandle = cHandle;
  m_ObList.AddTail( pHandle );

}
void ThreadTask::CloseThreadHandles()
{
  if ( m_ObList.GetCount() )
  {
    POSITION pos1, pos2;
    CHandle *pHandle = (CHandle *)NULL;
    //(CHandle類 相當簡單,只有一個成員函數m_ThreadHandle)
    DWORD dwExitCode = 0L;
    for( pos1=m_ObList.GetHeadPosition(); (pos2=pos1)! =POSITION(NULL); )
    {
      //歷遍所有已有的線程 句柄
      pHandle = DYNAMIC_DOWNCAST( CHandle, m_ObList.GetNext( pos1 ) );
      //獲得第pos1個handle
      VERIFY( ::GetExitCodeThread( pHandle->m_ThreadHandle, &dwExitCode ) );
      //獲得線程pHandle的當前狀態
      if ( dwExitCode != STILL_ACTIVE )
      //如果已 完成
      {
        //釋放當前句柄
         m_ObList.RemoveAt( pos2 );

        VERIFY( ::CloseHandle( pHandle->m_ThreadHandle ) );
         delete pHandle;
        pHandle = (CHandle *)NULL;
       }
    }
  }
}
ThreadTask::~ThreadTask()
{
}
ThreadTask & ThreadTask::GetThreadTask()
{
  //返回靜態ThreadTask對象, 以便ThreadManager類調用
  static ThreadTask Taker;
   return(Taker);
}
BOOL ThreadTask::IsValid()
{
   //是否已運行
  BOOL bValid_Status = FALSE;
  if ( (this != NULL) && AfxIsValidAddress( this, sizeof( ThreadTask ) ) )
    bValid_Status = TRUE;
  return( bValid_Status );
}

下面介紹線程ThreadTaskpro(); 該線程最主要的目的就是 調用ThreadTask的CloseThreadHandles()函數,實現如下:

DWORD WINAPI ThreadTaskpro( LPVOID pParam )
{
  HANDLE hCurrentThread = GetCurrentThread();
  //獲得該線程句柄
   SetThreadPriority( hCurrentThread, THREAD_PRIORITY_LOWEST );
   //設為最低
  while ( ThreadTask::GetThreadTask().m_bKeepGoing )
  {
    Sleep(500);
  //休息500mms

    ThreadTask::GetThreadTask().CloseThreadHandles();
  }

  SetThreadPriority( hCurrentThread, THREAD_PRIORITY_NORMAL );
  return( 0 );
}

ThreadTask類到這就介紹完了,下 面我們看看ThreadManager類的實現,其實它的工作已很小,就是啟動要管理的線 程(在構造函數中完成),並控制ThreadTask類。具體實現:

ThreadManager::ThreadManager(ThreadPro threadpro, LPVOID pParam)
{
  DWORD nThreadId = 0;
   _ASSERTE( ThreadTask::GetThreadTask().IsValid() );
  //運行ThreadTask類
  m_Handle = (HANDLE)::CreateThread(NULL,0,threadpro,(LPVOID) pParam,0,&nThreadId );
  //創建要管理的線程,並返回句柄
  if ( ThreadTask::GetThreadTask().m_bKeepGoing )
  {
    //如果ThreadTask運行了的話 
    ASSERT( m_Handle );
    ThreadTask::GetThreadTask().AddHandle( m_Handle );
    //把句柄加入ThreadTask類中,以便管理
  } 
}
ThreadManager::~ThreadManager()
{
}
BOOL  ThreadManager::RunThread()
{
  //運行線程
  return( ::ResumeThread( m_Handle ) != 0xFFFFFFFF );
}

整在機制就 介紹完了。

使用方法

使用方法相當簡單,比如說,我要運行進程 MyThread1,並傳入參數m_pro,只要用以下代碼就可以了:

ThreadManager ThreadManager( &MyThread1, (LPVOID)m_pro );
  ThreadManager.RunThread();

就可以了,用這種方法創 的線程,會自動由ThreadManager類管理,並在完成的工作時,自動釋放線程資源 。 我做了一個示例,大家可以試著運行一下。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved