Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

A thread wrapper class

3.11/5 (4 votes)
12 Apr 20071 min read 1   748  
A wrapper class of worker thread

Introduction

As a C++ programmer in Windows platform, I often use worker thread to deal with some tasks. For example I need to keep the GUI active while a computation is being performed.

But it isn't easy to implement the special synchronization feature for program beginner. To solve the problem, I write the ThreadModel class. The class written in Microsoft Visual C++ is a wrapper class that can control worker thread running exactly, such as Start, Stop and Wait thread until it is ended.

How is it working?

Screenshot - 1.jpg

C++
<pre lang="C++">// -----------
//  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; 
}

How to use it?

Screenshot - 2.jpg

The ThreadModel Class provides two ways to use it.
1.the UI-thread create the worker thread, the worker thread is running until the UI-thread execute "StopThread" method to end the worker thread. The derived class ThreadSample1 show the way.
2.the UI-thread create the worker thread, and it will wait for the worker thread until it is over. The derived class ThreadSampl2 show how to implement it;

<p>UINT ThreadSample::Run()<br />{<br />while(QueryExitEvent() == FALSE)<br />{<br />printf("%s\n","thread is running");<br />::Sleep(10);<br />}<br />return 0;<br />}</p>

<p>UINT ThreadSample2::Run()<br />{<br />for(int i = 0; i< 100; i++)<br />{<br />::Sleep(100);<br />printf("the thread2 is running\n");<br />}<br />return 0;<br />}</p>

<p><br />int _tmain(int argc, _TCHAR* argv[])<br />{<br />//the sample1 of thread<br />ThreadSample ts;<br />ts.StartThread();<br />::Sleep(10000);<br />//the main thread stop the working thread<br />ts.StopThread();<br />printf("the thread is over");</p>

<p>//the sample2 of thread<br />ThreadSample2 ts2;<br />ts2.StartThread();<br />//the main thread is waiting until the working is over<br />BOOL bRet = ts2.WaitThread();<br />{<br />printf("the thread2 is over");<br />}</p>

<p>return 0;<br />}</p>

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here