Introduction
Windows is an OS that does a "great job" of pretending to be a multitasking environment, so it would be a shame, if we programmers would not use this feature at least just for fun. This class should bring you this fun, and maybe (I hope) some knowledge. The class CAG_Thread
is just another win32 worker thread wrapper class. Yes, I am sure you could find many other classes that would do the same job just as fine or even better, but what I tried to accomplish is the simplicity. But as we all know the simplicity is subjective, so I will let you judge it for yourself.
Background
Some time ago I noticed that every once in a while I write a worker thread. Each time I need to write one, I copy and paste some functions, change them, and adjust them so they do the new job. After a while I got bored so I decided to write a class that would be very simple and still provide most common features used by me in a worker thread. So the class CAG_Thread
was born.
Using the code
The class should be very simple to use. It is intended to be a base class for another class, because it contains the pure virtual function ThreadMain()
which must be overridden. Here is the step by step use of the class:
- Include AG_Thread.cpp and AG_Thread.h into your project
- Derive a new class from
CAG_Thread
class
- Override in the new class the virtual function
ThreadMain()
- Use the newly created class to instantiate and start the thread by
StartThread()
function
Here is more detailed explanation with sample code which could be downloaded at the top of the article. I will assume that you should know how to add files to project. Follwoing is the second step of deriving a new class, in my case myThread
class from CAG_Thread
class. Following is the myThread
class definition.
#include "AG_Thread.h"
class myThread : public CAG_Thread
{
public:
myThread();
virtual ~myThread();
BOOL Work(CProgressCtrl *pProgress);
protected:
CProgressCtrl *m_pProgress;
UINT ThreadMain();
};
And here is (partly) the class implementation
BOOL myThread::Work(CProgressCtrl *pProgress)
{
if(pProgress == NULL)
return FALSE;
m_pProgress = pProgress;
return StartThread();
}
UINT myThread::ThreadMain()
{
m_pProgress->SetRange(0, 100);
m_pProgress->SetPos(0);
for(int i=0; i<101; ++i)
{
if(ShouldDie())
return 1;
m_pProgress->SetPos(i);
Sleep(50);
}
return 0;
}
Now we need to create instance of our class myThread
in the dialog box and use it. I simply used a button for starting the thread, but it is not limited to dialog boxes. So here is the function where the starting and ending of the thread occurs.
if(m_myThread.GetThreadStatus())
{
if(m_myThread.StopThread())
{
AfxMessageBox(_T("Thread killed successfully!"));
SetDlgItemText(IDC_START_STOP_BUTTON, _T("Start Thread"));
return;
}
AfxMessageBox(_T("Could not abort thread."));
}
else
{
if(m_myThread.Work(&m_progress))
{
SetDlgItemText(IDC_START_STOP_BUTTON, _T("Stop Thread"));
return;
}
AfxMessageBox(_T("Could not start thread."));
}
And that should be it. The demo included is the very basic example of what this class is good for. Please note that this class does not provide any synchronization objects, with the purpose to be as simple as possible. Also the demo is not a useful application, it simply shows the principal of using the class. This article is not very detailed, which again should add to the simplicity, but the code should be documented enough. English is my third language, so if you do not understand something (and experience tells me that you will not), please leave a message and I'll try to answer.