While ATL and WTL offer useful wrapper classes for most of the various objects a Win32
HANDLE can refer to, threads still have to be created and controlled using the API functions and handles directly. Admittedly, this is not a hard thing to do, but a clean object-oriented design can often help in avoiding bugs in multi-threaded applications.
The class collection I am going to present has often proved very useful to me. It contains handle wrappers for threads, as well as base classes that help implement worker and GUI threads.
The thread handle wrapper classes
There is not much to say about these classes. In the style usually followed by WTL,
CThreadT is a wrapper template class around a thread handle, which offers most of the Win32 API functions that take a thread handle as methods.
More conveniently, one will usually use the template instantiations
CThread will close the thread handle when it is destroyed, while
Creating a thread
Thread creation is implemented as the static method
CThreadT::Create, which is a wrapper around
CreateThread, if the "minimal use of CRT" option is set).
CThread thread = CThread::Create( (LPTHREAD_START_ROUTINE)
MyThreadProc, pParam );
Additional methods of CThread and CThreadHandle
CThreadT(HANDLE=NULL, DWORD=0) wraps a
CThread instance around the given thread handle and thread ID.
- There is also a copy constructor, which will call
DuplicateHandle on the given handle.
- The thread handle and ID can be retrieved with
- The methods
Exit are all wrappers around the respective API functions, their names mostly net of the word "thread".
- The method
Join performs a
WaitForSingleObject on the thread handle.
GUI threads are different from general worker threads in that they have a message queue. This means that we can post messages to a GUI thread using
The template class
CGuiThreadT, and its instantiations
CGuiThreadHandle, are just like the
CThreadT classes, with an additional method
PostThreadMessage for this end.
Causing a GUI thread to quit is usually a matter of posting the
WM_QUIT message to its queue. This is done by the
PostQuitMessage method. However, this method does not wrap the API of the same name, as the latter posts
WM_QUIT to the calling thread, which is not always the same.
The thread implementation classes
As ATL and WTL often differentiate between a handle to an object and its implementation (compare
CWindowImpl), I have chosen the same design for my thread classes (though the two cases are not perfectly comparable). The class
CThreadImpl provides the skeleton for a thread "implementation" class.
Derive your thread class from
CThreadImpl<T> and implement the
<PRE lang=c++>class CWorkerThread : public CThreadImpl<CWorkerThread>
// Do something useful...
// In some other function, that is called from your main thread:
CWorkerThread* pThread = new CWorkerThread;
The return value of
Run is the thread's exit code, like in the standard Win32
If you create an instance of
CWorkerThread, it will start running immediately. If you want to start it later, you can pass
CThreadImpl's constructor and call
Note that the constructor runs in the creating thread, so some of the thread initialization may have to be moved to the run method.
class CWorkerThread : public CThreadImpl<CWorkerThread>
if ( !Initialize() )
CWorkerThread* pThread = new CWorkerThread;
Implementation of GUI threads
CGuiThreadImpl uses the WTL class
CMessageLoop to manage a message loop. However, since
CAppModule wants to know about all
CMessageLoops in the process, this means you have to pass a pointer to your
CAppModule instance in the constructor.
To implement a GUI thread, derive your class from
CGuiThreadImpl and (optionally) override the following methods:
BOOL InitializeThread() to perform thread initialization. This is, for example, a good place to create windows. Return
FALSE to stop the thread.
void CleanupThread(DWORD) to perform cleanup tasks. The
DWORD parameter is the exit code from the message loop.
You can also add a message map to your thread class using the standard macro,
BEGIN_MSG_MAP. However, these will only be called for messages that are not directed to a window, i.e., where the
hWnd parameter is
Remember that you can access the thread's message loop using
CAppModule::GetMessageLoop(), so you can, for example, install additional
CMessageFilters. The place to do this would be the
The following example shows a simple GUI thread class which creates a timer and responds to the
class CTimerThread : public CGuiThreadImpl<CTimerThread>
m_nTimerId = ::SetTimer(NULL, 0, 1000, NULL);
return (m_nTimerId != 0);
LRESULT OnTimer(UINT, WPARAM, LPARAM, BOOL&)
The "timer thread" has to be created and stopped from the main thread:
class CMainFrame : ...
m_pTimerThread = new CTimerThread(&_Module);
Using the classes
All the thread classes are contained in a single header file, Thread.h, which you can download using the link given at the start of the article. To facilitate the classes, you just need to include Thread.h in your project.
If you would like to use the classes in a ATL-but-not-WTL project, you will need to remove all the GUI-thread related sections from the code. The other classes (
CThreadImpl) will work with "pure" ATL as well.
Using the set of classes presented in this article, it is possible to achieve a cleaner, more object-oriented design for multithreaded applications. The template design similar to the one found in other ATL/WTL classes makes it easy to understand and integrate.
CThreadT::Create now calls
_beginthreadex if possible (depending on
- Added method