Synchronizing Threads

The routines WaitForSingleObject and WaitForMultipleObjects enable threads to wait for a variety of different occurrences, such as thread completion or signals from other threads. They enable threads and processes to wait efficiently, consuming no CPU resources, either indefinitely or until a specified timeout interval has elapsed.

WaitForSingleObject takes an object handle as the first parameter and does not return until the object referenced by the handle either reaches a signaled state or until a specified timeout value elapses. The syntax is:

WaitResult = WaitForSingleObject (ObjectHandle, [ Timeout ] )

If you are using a timeout, specify the value in milliseconds as the second parameter. The value WAIT_INFINITE represents an infinite timeout, in which case the function waits until ObjectHandle completes.

WaitForMultipleObjects is similar, except that its second parameter is an array of Windows object handles. Specify the number of handles to wait for in the first parameter. This can be less than the total number of threads created, and its maximum is 64. The function can either wait until all events have completed, or resume as soon as any one of the objects completes.

Deadlocks occur when a thread waits for objects that never become available. Use the timeout parameter when there is a chance that the thread you are waiting for may never terminate. See Detecting Deadlocks in Multithreaded Win32 Applications," by Ruediger Asche, in the Microsoft Systems Journal, vol. 8, for a discussion of how to find and avoid potential resource collisions.

Suspending and Resuming Threads

You can use SuspendThread to stop a thread from executing. SuspendThread is not particularly useful for synchronization because it does not control the point in the code at which the thread's execution is suspended. However, you could suspend a thread if you need to confirm a user's input that would terminate the work of the thread. If confirmed, the thread is terminated; otherwise, it resumes.

If a thread is created in a suspended state, it does not begin to run until ResumeThread is called with a handle to the suspended thread. This can be useful for initializing the thread's state before it begins to run. Suspending a thread at creation can be useful for one-time synchronization, because ResumeThread ensures that the suspended thread will resume running at the starting point of its code.