CWinThread

Win32++

CWinThread Class

Description

A program or process can contain one or more threads.  Threads run independantly of each other, and can run concurrently. When used wisely, the use of multiple threads can make better use of the computer's resources, particularly multiple CPUs, allowing an application to be more responsive. The CWinThread class simplifies the use of threads with Win32++.

CWinThread Members

Operations

CWinThread
CWinThread();
CWinThread(PFNTHREADPROC pfnThreadProc, LPVOID pParam);
Constructs the CWinThread. GUI threads should use the first constructor. Worker threads should be created with the constructor which allows the ThreadProc and LPVOID to be specified.
CreateThread
void CreateThread(unsigned initflag = 0, unsigned stack_size = 0, LPSECURITY_ATTRIBUTES pSecurityAttributes = NULL);
Creates the thread. Valid argument values:
initflag - Either CREATE_SUSPENDED or 0
stack_size - Either the stack size or 0
pSecurityAttributes - Either a pointer to SECURITY_ATTRIBUTES or 0
GetAccelerators
HACCEL GetAccelerators() const;
Returns the handle to the accelerator table. GetAcceleratorsWindow
CWnd* GetAcceleratorsWindow() const;
Returns a pointer to the window for accelerator keys. GetThread
HANDLE GetThread() const;
Returns the thread handle. GetThreadID
int GetThreadID() const;
Returns the thread ID. GetThreadPriority
int GetThreadPriority() const;
Returns the thread's priority. ResumeThread
DWORD ResumeThread() const;
Resumes the execution of the thread. By default, the thread is created in a suspended state, and should be resumed when the application is ready to have the thread run. SetAccelerators
void SetAccelerators(HACCEL hAccel, CWnd* pWndAccel) const;
Sets handle of the accelerator table, and a pointer to the window used for accelerator keys. SetThreadPriority
BOOL SetThreadPriority(int nPriority) const;
Sets the thread's priority. SuspendThread
DWORD SuspendThread() const;
Suspends the execution of the thread.

Overridables

InitInstance
virtual BOOL InitInstance();
The function which runs when a GUI thread starts. Override this function to specify what the thread does when it starts. Return TRUE if the message loop should run, otherwise return FALSE.
MessageLoop
virtual int MessageLoop();
The MessageLoop function is called if InitInstance returns TRUE. Override this function if you wish to customise the message loop run by this thread.
OnIdle
virtual BOOL OnIdle(LONG lCount);
OnIdle is called to perform idle processing. The lCount is incremented each time OnIdle is called while the message queue is empty. Override OnIdle to perform small tasks. Larger tasks can be split up into pieces which are processed when lCount reaches specific values. Return TRUE to perform additional idle tasks, and return FALSE when there are no more tasks to perform.
PreTranslateMessage
virtual BOOL PreTranslateMessage(MSG Msg);
PreTranslateMessage processes the keyboard accelerator keys and calls CWnd::PreTranslateMessage for keyboard and mouse events.

Remarks

CWinThread supports the creation of both worker threads and GUI (Graphic User Interface) threads.

GUI Threads:

GUI threads (i.e. threads that have windows) should inherit from this class, use the first constuctor, and override InitInstance to specify what the thread does when it starts. If your thread is used to run one or more windows, InitInstance should return TRUE to start the MessageLoop.

Worker Threads:

Worker threads don't have windows and don't need a message loop. Worker threads don't need to inherit from this class. They can simply use the constructor which allows the ThreadProc and LPVOID to be specified.

Note:

Creating an instance of CWinThread doesn't create the thread. The CreateThread member function is used to create the thread.

It is your job to end the thread before CWinThread ends!  To end a thread with a message loop, post a WM_QUIT message to the thread. To end a thread without a message loop, set an event, and end the thread  when the event is received.

Programming Hints:  

  • It is never a good idea to use things like TerminateThread or ExitThread to end your thread. These represent poor programming techniques, and are likely to leak memory and resources.
  • Avoid using SendMessage between threads, as this will cause one thread to wait for the other to respond. Use PostMessage between threads to avoid this problem.
  • Access to variables and resources shared between threads need to be made thread safe. Having one thread modify a resource or variable while another thread is accessing it is a recipe for disaster.
  • Thread Local Storage (TLS) can be used to replace global variables to make them thread safe. With TLS, each thread gets its own copy of the variable.
  • Critical Sections can be used to make shared resources thread safe.
  • Window messages (including user defined messages) can be posted between GUI threads to communicate information between them.
  • Events (created by CreateEvent) can be used to communicate information between threads (both GUI and worker threads).
  • Avoid using sleep to synchronise threads. The various wait functions (e.g. WaitForSingleObject) will be better for thread synchronisation.

About Threads:
Each program that executes has a "process" allocated to it. A process has one or more threads. Threads run independently of each other. It is the job of the operating system to manage the running of the threads, and do the task switching between threads as required. Systems with multiple CPUs will be able to run as many threads simultaneously as there are CPUs.

Threads behave like a program within a program. When the main thread starts, the application runs the WinMain function and ends when WinMain ends. When another thread starts, it too will run the function provided to it, and end when that function ends.

Summary Information

Header file wincore.h
Win32/64 support Yes
WinCE support Yes