65.9K
CodeProject 正在变化。 阅读更多。
Home

线程包装器类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.11/5 (4投票s)

2007年4月12日

1分钟阅读

viewsIcon

37036

downloadIcon

783

工作线程的包装器类。

引言

作为 Windows 平台上的 C++ 程序员,我经常使用工作线程来处理一些任务。例如,我需要在执行计算的同时保持 GUI 处于活动状态。

但对于程序初学者来说,实现特殊的同步功能并不容易。为了解决这个问题,我编写了 ThreadModel 类。该类使用 Microsoft Visual C++ 编写,是一个可以精确控制工作线程运行的封装类,例如启动、停止和等待线程结束。

它是如何工作的?

Screenshot - 1.jpg

// -----------
//  ThreadModel

// ------------
class  ThreadModel  
{
public:
//---------------------
// functions that be used to control the thread running.
//---------------------
// start the thread
BOOL StartThread();
// stop the thread
void StopThread(); 
BOOL WaitThread(DWORD nTimeOut = INFINITE); // virtual function
protected:
//---------------------
// override functions
//---------------------
virtual void BeforeThread();
virtual void AfterThread(); 
// the thread function
virtual UINT Run() = 0;
protected:
/// Query if the the method "stop thread" has been executed.the paramater "dwDuration" is waiting time
/// if it is "0",the method will return at once.
BOOL QueryExitEvent(DWORD dwDuration = 0);
/// Query the the thread if existing 
BOOL IsThreadRunning() { return (m_hThread != 0); }
private:
/// the static thread function
static UINT __stdcall __ThreadProxyProc(LPVOID pParam);
protected:
ThreadModel();
virtual ~ThreadModel();
protected:
HANDLE m_hThread;//<the handle of thread
private:
BOOL m_bLowCpuPriority; //<
HANDLE m_hEvtThreadStart; //< 
HANDLE m_hEvtThreadOver; //<
HANDLE m_hEvtUserAbort; //<
};
1.StartThread
BOOL ThreadModel::StartThread()
{
if (m_hThread != NULL) return FALSE;
::ResetEvent(m_hEvtUserAbort);
::ResetEvent(m_hEvtThreadOver);
UINT nThreadID = 0;
//start the new worker thread
int nVal = _beginthreadex(NULL, 0, __ThreadProxyProc, (void *)this, 0, &nThreadID);
if(nVal <= 0) 
{
return FALSE;
}
m_hThread = reinterpret_cast<HANDLE>(nVal);
if (m_bLowCpuPriority)
SetThreadPriority(m_hThread, THREAD_PRIORITY_IDLE);
// wait thread start
DWORD nWait = ::WaitForSingleObject(m_hEvtThreadStart, INFINITE);
::ResetEvent(m_hEvtThreadStart);
if (nWait != WAIT_OBJECT_0)
return FALSE;
return TRUE;
}
2.Stop thread
void ThreadModel::StopThread()
{ 
if (m_hThread != NULL)
{ 
// try to Stop thread
::SetEvent(m_hEvtUserAbort);
// default wait 5 secs
if (::WaitForSingleObject(m_hEvtThreadOver, 5 * 1000) == WAIT_OBJECT_0)
{
// ok . 
::ResetEvent(m_hEvtThreadOver);
}
else 
{ 
// kill thread,but it is dangerous
::TerminateThread(m_hThread, 1);
m_hThread = NULL;
} 
}
else
::ResetEvent(m_hEvtThreadOver);
}
3.Wait thread over
BOOL ThreadModel::WaitThread(DWORD nTimeOut /*= INFINITE*/)
{
if (NULL == m_hThread)
return FALSE;
BOOL result = (WaitForSingleObject(m_hEvtThreadOver, nTimeOut) == WAIT_OBJECT_0)?true:false;
if (!result)
{
::TerminateThread(m_hThread, 1); 
m_hThread = NULL;
}
return result; 
}

如何使用它?

Screenshot - 2.jpg

ThreadModel 类提供了两种使用方法。
1. UI 线程创建工作线程,工作线程运行直到 UI 线程执行“StopThread”方法来结束工作线程。派生类 ThreadSample1 展示了这种方法。
2. UI 线程创建工作线程,并等待工作线程完成。派生类 ThreadSample2 展示了如何实现它;

UINT ThreadSample::Run()
{
while(QueryExitEvent() == FALSE)
{
printf("%s\n","线程正在运行");
::Sleep(10);
}
return 0;
}

UINT ThreadSample2::Run()
{
for(int i = 0; i< 100; i++)
{
::Sleep(100);
printf("线程2正在运行\n");
}
return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
//线程示例1
ThreadSample ts;
ts.StartThread();
::Sleep(10000);
//主线程停止工作线程
ts.StopThread();
printf("线程已结束");

//线程示例2
ThreadSample2 ts2;
ts2.StartThread();
//主线程等待工作完成
BOOL bRet = ts2.WaitThread();
{
printf("线程2已结束");
}

return 0;
}

© . All rights reserved.