I have a Windows GUI app that uses a thread for a computation intensive call. It works fine.

From what I understand the thread is terminated when my thread function returns which means that I dont need to add a a termination to it.

However, I don't want the user to be able to run this computation intensive command while a thread is already running. How do I know if a thread is running? I can see a solution (primitive...) in which I have a variable in the main program that I set to TRUE when I enter a computation and to FALSE when the computation is done. Is there a better way? I would then check the value of this parameter prior to entering a new computation.

when I create my thread I don't give it a handler. I can do that but the thread is created in the WM_COMMAND case for the command. Would I declare this handle in the main program first then and use it to get the thread status or something along those lines?

Any input is very welcome!!!


These types of issues fall under the canopy of 'Windows Synchronization Objects' and lead into such topics as Mutexes (Mutual Exclusion Synchronization Objects) and semiphores. In the program I posted yesterday there was a very simplistic method of not allowing the user to launch additionl threads until the one underway was finished by simply disabling the button control that starts the thread until the thread is finished, and then re-enabling it. If you want something more sophisticated, such as the ability to cancel mid way through, then you need the signaling potentials of the above listed sychronization topics.

I'm personally just beginning to use these things - not so much mutexes, but threads & such. Up to this point most of my apps are single threaded. When lengthy procedures are running I usually just change the cursor to an hourglass or use a progress bar, and most of my computations with the speed of modern computers only take several seconds.

However, if you want to get into this the last chapter of Brent E. Rector and Joseph M. Newcommer's 'Win32 Programming' book cover Synchronization objects in pretty gory detail. One place I've used mutexes successfully is I create one based on a file name chosen by the user in an open file dialog box, and I don't let the user open a second invocation of the same file. This I do in my Windows CE data recorder programs. The object is in a signalled state and that can be tested for every file the user tries to open. It essentially creates a global entity within the Windows Operating System. Hope this info helps.

Another thought, rather than getting into the whole data synchronization topic, and if you're willing to entertain simplistic solutions, is just to use the EnableWindow(), IsWindowEnabled() Api functions, as I previously alluded. Simply disable the button or menu command until the process is finished, then re-enable it. Also check out the IsWindowEnabled() function. It is essentially your TRUE/FALSE switch in a more elegant costume.

Here's WaitForSingleObject()


The WaitForSingleObject function returns when one of the following occurs: 

The specified object is in the signaled state. 

The time-out interval elapses. 

DWORD WaitForSingleObject
  HANDLE hHandle,        // handle to object to wait for
  DWORD dwMilliseconds   // time-out interval in milliseconds

Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section. 

Windows NT: The handle must have SYNCHRONIZE access. For more information, see Standard Access Rights. 

Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses. 
Return Values
If the function succeeds, the return value indicates the event that caused the function to return. This value can be one of the following. 

Value Meaning 

WAIT_ABANDONED The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled. 
WAIT_OBJECT_0 The state of the specified object is signaled. 
WAIT_TIMEOUT The time-out interval elapsed, and the object's state is nonsignaled. 

If the function fails, the return value is WAIT_FAILED. To get extended error information, call GetLastError. 

The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters an efficient wait state. The thread consumes very little processor time while waiting for the object state to become signaled or the time-out interval to elapse.

Before returning, a wait function modifies the state of some types of synchronization objects. Modification occurs only for the object whose signaled state caused the function to return. For example, the count of a semaphore object is decreased by one. 

The WaitForSingleObject function can wait for the following objects: 

Change notification 
Console input 
Waitable timer 
For more information, see Synchronization Objects.

Use caution when calling the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and COM CoInitialize. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.