Home | Overview | How Do I | Sample
A worker thread is commonly used to handle background tasks that the user shouldn’t have to wait for to continue using your application. Tasks such as recalculation and background printing are good examples of worker threads. This article details the steps necessary to create a worker thread. Topics include:
Creating a worker thread is a relatively simple task. Only two steps are required to get your thread running: implementing the controlling function and starting the thread. It is not necessary to derive a class from CWinThread. You can if you need a special version of CWinThread, but it is not required for most simple worker threads. You can use CWinThread without modification.
There are two overloaded versions of AfxBeginThread: one for user-interface threads and one for worker threads. To begin execution of your worker thread, call AfxBeginThread providing the following information:
AfxBeginThread creates and initializes a CWinThread object for you, starts it, and returns its address so you can refer to it later. Checks are made throughout the procedure to make sure all objects are deallocated properly should any part of the creation fail.
The controlling function defines the thread. When this function is entered, the thread starts, and when it exits, the thread terminates. This function should have the following prototype:
UINT MyControllingFunction( LPVOID pParam );
The parameter is a single 32-bit value. The value the function receives in this parameter is the value that was passed to the constructor when the thread object was created. The controlling function can interpret this value in any manner it chooses. It can be treated as a scalar value, or a pointer to a structure containing multiple parameters, or it can be ignored. If the parameter refers to a structure, the structure can be used not only to pass data from the caller to the thread, but also to pass data back from the thread to the caller. If you use such a structure to pass data back to the caller, the thread will need to notify the caller when the results are ready. For information on communicating from the worker thread to the caller, see the article Multithreading: Programming Tips.
When the function terminates, it should return a UINT value indicating the reason for termination. Typically, this exit code is 0 to indicate success with other values indicating different types of errors. This is purely implementation dependent. Some threads may maintain usage counts of objects, and return the current number of uses of that object. To see how applications can retrieve this value, see the article Multithreading: Terminating Threads.
There are some restrictions on what you can do in a multithreaded program written with the Microsoft Foundation Class Library. For descriptions of these restrictions and other tips on using threads, see the article Multithreading: Programming Tips.
This example shows how to define a controlling function and use it from another portion of the program.
UINT MyThreadProc( LPVOID pParam )
{
CMyObject* pObject = (CMyObject*)pParam;
if (pObject == NULL ||
!pObject->IsKindOf(RUNTIME_CLASS(CMyObject)))
return 1; // if pObject is not valid
// do something with 'pObject'
return 0; // thread completed successfully
}
// inside a different function in the program
.
.
.
pNewObject = new CMyObject;
AfxBeginThread(MyThreadProc, pNewObject);
.
.
.