In most cases where you want to block the execution of a thread, you would use one of the two wait functions, WaitForSingleObject or WaitForMultipleObjects, to wait for one or more waitable objects to be signalled. Waitable objects include mutex, semaphore, event, file, file mapping, named and anonymous pipe, process, thread, and console input objects. The execution of a thread is blocked if the object for which it is waiting is not signalled. As with a suspended thread, a waiting thread consumes very little processor time. The advantage of using the wait functions instead of SuspendThread and ResumeThread is that you can control precisely which code instruction will be executed when the thread is released. For example, an application could create a thread to perform some task that occurs at irregular intervals, using an event object to signal the thread when it is time to execute. Because the thread was ready and waiting, the task could be performed without the overhead of thread creation.
For the threads of a single process, Critical Section objects provide another (and slightly more efficient) means of synchronization. A Critical Section is used like a mutex to allow only one thread at a time to use the protected resource. Instead of the wait functions mentioned above, a thread uses the EnterCriticalSection function to request ownership of a Critical Section. If it is already owned by another thread, the requesting thread will be blocked. Once it receives ownership, the thread is free to use the protected resource. The execution of the other threads of the process is not affected unless they attempt to enter the same Critical Section. For more information on Critical Sections and synchronization, see Chapter 4, “Synchronization.”