Creating, Exiting, and Terminating Threads

The CreateThread function used to create a new thread expects several parameters that control how the system creates the thread and the instructions that the thread runs. Although it is possible to set most of these parameters to null or zero, it is necessary to provide at least a pointer to an application-defined function that the thread is supposed to execute. This function typically defines the core processing instructions for the thread, although you can also call other functions from within this function. It is important to pass the core function as a static reference to CreateThread because the linker must be able to determine the core function's starting address at compile time. Passing a non-static function pointer does not work.

The following code listing is copied from the Explorer.cpp file that you can find in the %_WINCEROOT% PublicShellOAKHPCExplorerMain folder. It illustrates how to create a thread.

void DoStartupTasks() {

 HANDLE hThread = NULL;

 // Spin off the thread which registers and watches the font dirs

 hThread = CreateThread(NULL, NULL, FontThread, NULL, 0, NULL);

 if (hThread) {

  CloseHandle(hThread);

 }

 // Launch all applications in the startup folder

 ProcessStartupFolder();

}

This code specifies FontThread as the new thread's core function. It immediately closes the returned thread handle because the current thread does not need it. The new thread runs parallel to the current thread and implicitly exits upon returning from the core function. This is the preferred way to exit threads because it enables C++ function cleanup to occur. It is not necessary to explicitly call ExitThread.

However, it is possible to explicitly call the ExitThread function within a thread routine to end processing without reaching the end of the core function. ExitThread invokes the entry point of all attached DLLs with a value indicating that the current thread is detaching, and then deallocates the current thread's stack to terminate the current thread. The application process exits if the current thread happens to be the primary thread. Because ExitThread acts on the current thread, it is not necessary to specify a thread handle. However, you must pass a numeric exit code, which other threads can retrieve by using the GetExitCodeThread function. This process is useful to identify errors and reasons for the thread exiting. If ExitThread is not explicitly called, the exit code corresponds to the return value of the thread function. If GetExitCodeThread returns the value STILL_ACTIVE, the thread is still active and running.

Although you should avoid it, there can be rare situations that leave you no other way to terminate a thread except for calling the TerminateThread function. A malfunctioning thread destroying file records might require this function. Formatting a file system might need you to call TerminateThread in debugging sessions while your code is still under development. You need to pass the handle to the thread to be terminated and an exit code, which you can retrieve later by using the GetExitCodeThread function. Calling the TerminateThread function should never be part of normal processing. It leaves the thread stack and attached DLLs behind, abandons critical sections and mutexes owned by the terminated thread, and leads to memory leaks and instability. Do not use TerminateThread as part of the process shutdown procedure. Threads within the process can exit implicitly or explicitly by using the ExitThread function.

Managing Thread Priority

Each thread has a priority value ranging from zero to 255, which determines how the system schedules the thread to run in relationship to all other threads within the process and between processes. On Windows Embedded CE, the core Win32 API includes four thread management functions that set the priority of a thread as follows.

¦ Base priority levels Use the SetThreadPriority and SetThreadPriority functions to manage the thread priority at levels compatible with early versions of Windows Embedded CE (zero through seven).

¦ All priority levels Use the CeSetThreadPriority and CeGetThreadPriority functions to manage the thread priority at all levels (zero through 255).

NOTE Base priority levels

The base priority levels zero through seven of earlier versions of Windows Embedded CE are now mapped to the eight lowest priority levels 248 through 255 of the CeSetThreadPriority function.

It is important to keep in mind that thread priorities define a relationship between threads. Assigning a high thread priority can be detrimental to the system if other important threads run with lower priority. You might achieve better application behavior by using a lower priority value. Performance testing with different priority values is a reliable manner of identifying the best priority level for a thread in an application or driver. However, testing 256 different priority values is not efficient. Choose an appropriate priority range for your threads according to the purpose of your driver or application as listed in Table 3-10.

Table 3-10 Thread priority ranges

Range Description
zero through 96 Reserved for real-time drivers.
97 through 152 Used by default device drivers.
153 through 247 Reserved for real-time below drivers.
248 through 255 Maps to non-real-time priorities for applications.

Suspending and Resuming Threads

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату