All code executes within a thread in Windows CE. A thread contains a stack and a program counter among other things. 
A thread runs at a priority level from 0 to 255, with 0 being the highest priority. Higher priority threads run before lower priority threads and can therefore block lower priority threads from running. The priority level of a thread can be changed.
When a thread is scheduled to run, it will run for a period of time known as quantum or until the thread gives up its quantum by blocking. The quantum for a thread can be changed.
When a thread blocks or its quantum expires, the OS will save the state of CPU registers for the thread. Then when the thread is scheduled to run again, the state of the CPU registers will be restored.
Writing a Thread
Writing a thread starts writing a function that returns a DWORD and takes as a parameter a pointer to a DWORD. The function can contain a loop that repeats the same instructions, or it can simply execute some instructions and then end.
Example Thread:
DWORD WINAPI ExampleThread(LPVOID pParam)
{
                BOOL Toggle = 0;
                DWORD Pin = *(DWORD *)pParam;
 
                while( 1 )
                {
                                Sleep( 1000 );
                                ToggleGPIO( Toggle, Pin );
                                Toggle ^= 1;
                }
                return 0;             
}
This thread simply runs in a loop forever. Each iteration of the loop the thread will sleep for 1 second, then toggle a GPIO pin by calling ToggleGPIO(). ToggleGPIO() is an imaginary function, I will leave it up to you to write on if you want to use this function.
Starting a Thread
The primary thread of a process is started automatically when the process starts. All other threads will be started by calling CreateThread().
Example starting ExampleThread:
                DWORD ThreadID;
                HANDLE hExampleThread;
                DWORD GPIOPin = 100;
 
                hExampleThread = CreateThread( NULL,
                                                                                0,
                                                                                ExampleThread,
                                                                                &GPIOPin,
                                                                                0,
                                                                                &ThreadID );
This starts ExampleThread and passes a pointer to the GPIOPin. Caution should be used with the parameter though because if GPIOPin is on the stack, the data could be invalid when the thread dereferences it. So the parameter should either be global, or allocated on the heap.
Thread Priority
The thread priority can be changed by calling CeSetThreadPriority() or SetThreadPriority(). CeSetThreadPriority() and CeGetThreadPriority() became available in Windows CE 3.0 to provide a way to set the priority from 0 to 255. Prior to Windows CE 3.0, the number of available thread priorities was 8.
SetThreadPriority() and GetThreadPriority() are somewhat obsolete and is primarily maintained in the OS to maintain backward compatibility with applications written prior to Windows CE 3.0, and the many written since then that still call these functions. SetThreadPriority() does have one advantage when used from an application; it limits the ability to change the priority to an overly high priority.
Example raising the thread priority using the thread handle:
                DWORD Priority = CeGetThreadPriority( hExampleThread );
                CeSetThreadPriority( hExampleThread, Priority - 1 );
 
Example raising the thread priority using GetCurrentThread():
                DWORD Priority = CeGetThreadPriority( GetCurrentThread() );
                CeSetThreadPriority( GetCurrentThread(), Priority - 1 );
It is not necessary to get the thread priority prior to setting the priority.
Thread Quantum
The Windows CE default thread quantum is 100 milliseconds (starting with Windows CE 3.0), but the OEM can change the default thread quantum so the default on some devices could be different.
CeSetThreadQuantum() and CeGetThreadQuantum() can be used to set and get a thread’s quantum.
Example setting the thread quantum:
                CeSetThreadQuantum( GetCurrentThread(), 20 );
Adjusting the thread priority and/or quantum is one way to improve the performance of a thread or the system as a whole.
Giving up Quantum (Blocking)
Threads should play nice with the system by stopping to allow other threads at lower priorities to run. Threads do this by giving up their quantum, also known as blocking. While Windows CE is a preemptive multitasking OS, no system can work well if a thread runs 100% and prevents lower priority threads to run. Even other threads at the same priority may not be able run often enough to provide expected response to the user.
Threads block by calling:
·         Sleep()
·         WaitForSingleObject()
·         WaitForMultipleObject()
·         Calling another function that ultimately calls one of the above functions
Another reason to block is that many Windows CE systems run on battery power. When no threads are scheduled to run, the OEM can put the CPU in a lower power mode to save battery power, but they cannot do that if a thread is using 100% of the CPU time.
 
Copyright © 2009 – Bruce Eitman
All Rights Reserved