Click to See Complete Forum and Search --> : How to tell if a Worker thread is suspended


charris67
October 6th, 2005, 01:06 PM
I'm kinda new to threads. I have a worker thread that is frequently suspended and resumed. How can I tell if it is currently suspended so that the program won't call SuspendThread more times than ResumeThread?

would like to do something like this....

if(thread is suspended)
{
resume thread;
}

Thanks

Siddhartha
October 6th, 2005, 01:43 PM
Using SuspendThread (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/suspendthread.asp) to momentarily stop a thread's execution is not a good practise. For one, the state of the thread, and the point of execution when it is suspended is unknown. For another, you need to Resume as often as you suspended for the thread to really start working!

A better thing to do would be to Wait on a Synchronization object like an Event for instance. One that could be signalled from outside.
Look up -


WaitForSingleObject (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitforsingleobject.asp)
CreateEvent (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createevent.asp)
Here is what MSDN has to say - SuspendThread -

This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately. Given the options, avoid it... ;)

charris67
October 6th, 2005, 02:04 PM
Well the app only has the main thread and a worker thread. The worker thread within a safe state suspends itself when it needs to within the logic of the program. This is the only way the worker thread is suspended. The main thread resumes the thread.

To be more specific, this is a boardgame type app where the user makes a move and if it's the computer's turn to play the thread is resumed. After the thread has made the computer's move it suspends itself so that the user can make a move. After the user's move, the worker thread is resumed from a safe point.

I tried using ::Sleep(300) in the worker thread while constantly checking for IsComputerTurn(), but this kinda hogs the cpu.

Is the above good/safe method of doing this? Or should I use WaitForSingleObject using IsComputerTurn()?

Thanks again.

Siddhartha
October 6th, 2005, 02:27 PM
Actually, your application is an excellent case for Performance Optimization and learning Thread Synchronization, both. :)To be more specific, this is a boardgame type app where the user makes a move and if it's the computer's turn to play the thread is resumed. After the thread has made the computer's move it suspends itself so that the user can make a move. To streamline your application logic, and to keep from sleeping, you could use Events.

So, in your main thread, you could create an event object using CreateEvent (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createevent.asp).
Like this -
HANDLE hMyThreadSyncEvent = CreateEvent ( NULL
, FALSE // TRUE: manual reset
, FALSE // TRUE: Wait will yield at first go
, NULL ); You would pass hMyThreadSyncEvent as a parameter to your thread function (or alternatively, have it global, or accessible to your thread function via other methods)

Now, inside your thread function, you would wait on this HANDLE using WaitForSingleObject (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitforsingleobject.asp).
Like this - // Inside your worker thread
WaitForSingleObject (hMyThreadSyncEvent, INFINITE);Perhaps, your thread contains a loop, and the beginning of the loop is where you would wait.

Now, inside the main thread at the point where User Input (Move) is known, you would signal the Worker Thread to resume using SetEvent (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/setevent.asp).
Like this -
// Inside the main thread when its computer's turn
SetEvent (hMyThreadSyncEvent); Now, when you Set the event, the worker thread waiting on the Event will be released and thus the computer will execute it's move.

As the second parameter to CreateEvent is FALSE, the thread will automatically wait on the next loop, unless SetEvent is called again (and this will happen only when the user makes a move.)

So, I hope the application of thread synchronization to your game is clear, now. As you can see - you have avoided using Sleep for pre-determined amounts of time, and you have avoided consuming CPU by calling a function repetitively in a loop.

Welcome to Win 32 Thread Synchronization. ;)

charris67
October 6th, 2005, 02:50 PM
Thanks Siddhartha for the very good explanation and elegant solution. I'll implement this.

BYW, how do you tell if a thread is suspended or running? I'm still curious for future reference. :)

Thanks again.

Siddhartha
October 6th, 2005, 02:59 PM
Thanks Siddhartha for the very good explanation and elegant solution. I'll implement this.You are welcome... ;)

BYW, how do you tell if a thread is suspended or running? I'm still curious for future reference. AFAIR, there is no reliable way to find this out.

But, you can implement your own logic, like this - bool bRunning = false;
void SuspendMyThread ()
{
if (bRunning)
{
SuspendThread (hMyThread);
bRunning = false;
}
}

void ResumeMyThread ()
{
if (!bRunning)
{
ResumeThread (hMyThread);
bRunning = true;
}
}

MikeAThon
October 6th, 2005, 05:01 PM
Using SuspendThread (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/suspendthread.asp) to momentarily stop a thread's execution is not a good practise. ...
I want to echo Siddharhta's recommendation to avoid SuspendTHread. It's particularly bad practice to use SuspendThread in a situation (like you described) where a thread suspends itself, and relies on another thread to call ResumeThread. This can cause the target thread to become permanently suspended, since there's no synchronization betweeen the suspending and the resuming; as a conseuence, it's possible for ResumeThread to be called before the target thread has completed its call to SuspendThread, resulting in a frozen thread that will never be resumed again because you think that it has already been resumed.

If you use SuspendThread at all, it should only be used in a debug-like environment (per the documentation), where the target thread is both suspended and resumed by another thread, probably the "main" thread. Don't split the calls to suspend and resume between different threads.

Mike

cpp_prgmer
September 11th, 2006, 06:31 AM
Ok i hav a somewhat different problem at hand. I have a thread pool of which we have some running threads.
Now based on some condition I would like to either resume one of the sleeping threads or suspend of the running threads at random.
In this case, how can I make use of events?

Cud some1 suggest an alternative to this situation?

Siddhartha
September 11th, 2006, 07:54 AM
In this case, how can I make use of events?What you can do is that with every thread you create, also create an event solely for that thread. Pass the event handle as a parameter to the thread and maintain a map of thread handle to (it's) event handle in the main (i.e. controlling) thread.

Inside the thread, at regular instances, one can query if the event is signalled using WaitForSingleObject.

The controlling thread can then use SetEvent (hThreadEventHandle) to release the thread or use ResetEvent (hThreadEventHandle) to make the thread stop.