Click here to Skip to main content
15,888,610 members
Articles / Programming Languages / C++
Article

A thread wrapper class

Rate me:
Please Sign up or sign in to vote.
3.11/5 (4 votes)
12 Apr 20071 min read 36.2K   743   20   3
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


Written By
Web Developer
China China
Bony Chen, a senior software engineer, specializes in C++, COM, C#, ASP.net, ISAPI. He has nearly seven years of software development experience, and has successfully developed many influential software products, such as SPES, CSO, QQ (a famous IM tool in China).
And now he is focusing on P2P technology. He aims at being an expert in software development, software consulting, software components and computer science.
If you have any opinions or questions in software area, please contact bonyren@163.com.

Comments and Discussions

 
GeneralName Pin
Just someone else12-Apr-07 20:38
Just someone else12-Apr-07 20:38 
GeneralA few suggestions Pin
Ali Rafiee12-Apr-07 13:48
Ali Rafiee12-Apr-07 13:48 
GeneralRe: A few suggestions Pin
Bony Chen12-Apr-07 15:28
Bony Chen12-Apr-07 15:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.