這個作爲大多數人詬病的東西,調用Win32 API複雜,調用開源庫pthread、boost::thread竟然沒有暫停,還得加鎖實現,比較麻煩。還有就是網上的代碼,給出了是給出了,但竟然不說說如何使用,看得我蛋疼。於是我就封裝了一個庫,覺得網上的庫麻煩可以試試我這個,通過臨界區加鎖。如果同學們遇到什麼問題可以提出來。
hThread.h
#ifndef _H_THREAD_H_
#define _H_THREAD_H_
#pragma once
#include <Windows.h>
#define hThread_Enter(o) ::EnterCriticalSection (&(o)->cs)
#define hThread_Leave(o) ::LeaveCriticalSection (&(o)->cs)
typedef void (*pFunc)();
class hThread {
volatile bool isPause;
bool isNew;
protected:
HANDLE h_hThread;
DWORD h_dwID;
virtual void Thread () = 0;
void _initCritical ();
void _releCritical ();
public:
void updateCritical ();
volatile bool nearStop;
CRITICAL_SECTION cs;
hThread ();
~hThread ();
bool Start (bool bEnter);
bool Stop (bool bEnter);
bool Pause (bool bEnter);
bool IsPause (bool bEnter);
bool IsExist (bool bEnter);
static DWORD WINAPI _thread (hThread* o);
};
#endif //_H_THREAD_H_
hThread.cpp
#include "hThread.h"
#define _hThread_Enter(cs) if (!bEnter) ::EnterCriticalSection (cs)
#define _hThread_Leave(cs) if (!bEnter) ::LeaveCriticalSection (cs)
void hThread::_initCritical () {
RtlZeroMemory (&this->cs, sizeof (CRITICAL_SECTION));
::InitializeCriticalSection (&this->cs);
}
void hThread::_releCritical () {
::DeleteCriticalSection (&this->cs);
}
void hThread::updateCritical () {
this->_releCritical ();
this->_initCritical ();
}
hThread::hThread () {
this->_initCritical ();
this->nearStop = this->isPause = this->isNew = false;
this->h_hThread = NULL;
this->h_dwID = 0;
}
hThread::~hThread () {
this->Stop (false);
this->_releCritical ();
}
bool hThread::Start (bool bEnter) {
bool bRet;
_hThread_Enter (&this->cs);
if (this->isPause) {
bRet = -1 == ::ResumeThread (this->h_hThread);
} else {
this->nearStop = false;
if (this->isNew) {
this->updateCritical ();
} else {
this->isNew = true;
}
bRet = !(this->h_hThread = ::CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) hThread::_thread, this, 0, &this->h_dwID));
}
this->isPause = false;
_hThread_Leave (&this->cs);
return bRet;
}
bool hThread::Stop (bool bEnter) {
if (this->nearStop) ::WaitForSingleObject (this->h_hThread, 100);
_hThread_Enter (&this->cs);
if (this->IsExist(true)) {
::TerminateThread (this->h_hThread, 0);
::CloseHandle (this->h_hThread);
this->h_hThread = NULL;
}
_hThread_Leave (&this->cs);
return true;
}
bool hThread::Pause (bool bEnter) {
if (this->nearStop) ::WaitForSingleObject (this->h_hThread, 100);
_hThread_Enter (&this->cs);
if (this->IsExist(true)) {
::SuspendThread (this->h_hThread);
this->isPause = true;
}
_hThread_Leave (&this->cs);
return this->isPause;
}
bool hThread::IsPause (bool bEnter) {
return this->IsExist (bEnter) && this->isPause;
}
bool hThread::IsExist (bool bEnter) {
_hThread_Enter (&this->cs);
bool bRet = false;
DWORD dwExit = 0;
if (this->h_hThread && this->h_hThread != INVALID_HANDLE_VALUE && ::GetExitCodeThread (this->h_hThread, &dwExit)) {
bRet = (STILL_ACTIVE == dwExit);
}
_hThread_Leave (&this->cs);
return bRet;
}
DWORD WINAPI hThread::_thread (hThread* o) {
o->nearStop = o->isPause = false;
o->Thread ();
hThread_Enter (o);
::CloseHandle (o->h_hThread);
o->h_hThread = NULL;
hThread_Leave (o);
return 0;
}
兩個文件。使用方法:
1、引用hThread.h,不解釋
2、創建一個類,繼承至hThread,並實現virtual void Thread方法
class testThread : public hThread {
public:
testThread () { }
~testThread () { }
virtual void Thread () {
hThread_Enter (this);
//...
hThread_Leave (this);
}
};
這裏說明一下, hThread_Enter (this); 和 hThread_Leave (this); 之間的代碼爲臨界區內部代碼,如果不想在這段代碼內部Pause的話。
還有就是線程內部多個臨界區之間最好加一個Sleep(10),方便外部暫停線程。
3、實例化
testThread t = new testThread();
4、接下來就是創建線程。
t->Start(true);
5、然後就自由了,各種Start、Pause、Stop隨便用。
可能有同學會疑問爲何調用Start、Pause、Stop都要傳一個參數,我在這兒簡要說明下,參數的意思代表是否已經進入臨界區。假如已經進入臨界區了就傳true,否則傳false。由於線程內部爲了安全,用了非常多的臨界區加鎖,於是設置了這個參數,用於優化代碼效率吧。另外,這個參數非常重要,假如進入臨界區後不能傳false,否則卡死!原因自行分析。
另外,有兩個問題需要同學們注意,一個是創建線程以及暫停線程後的恢復均爲Start函數實現,另一個是假如一個線程結束後再次創建一個線程,傳入的Start參數必須爲true