Question

Actually i am using this code and works ok, but i 'am wondering if is the correct way.

  while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
    Application.ProcessMessages;

  ShowMessage('i am done');
Was it helpful?

Solution

Calling Application.ProcessMessages is generally considered a code smell. Let your main thread idle if it's got nothing to do.

If you ran a company and needed one of your workers to run to the store and grab some much-needed supplies, would you then pace by the door until he got back, or would you prefer to sit in your office and rest and wait for him, and find out that the supplies are here because you hear him walk through the door? Either way, he'll take the same amount of time, but the first way's gonna wear your legs out.

Similarly, instead of having your UI watch the thread, have the thread report back to the UI. One way to do this is to have the thread use PostMessage to send a custom message to the form that launched it once it's finished, and put a message handler on the form to respond to it.

OTHER TIPS

The VCL TThread class has its own WaitFor() method that pumps the main message queue internally when called within the main thread context:

MyThread.WaitFor; 
ShowMessage('i am done'); 

It looks correct (if correct means it do the work). What I would change is to wait for a bit more time (50ms looks good to maintain the application responsive) while not eating CPU.

while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
  Application.ProcessMessages;
ShowMessage('i am done');

Sure there are other ways to do it... <joke>but I usually apply one of the main engineering principles:

if it works, don't touch it!</joke>

I agree with Mason Wheeler's remark, the main thread is best left to do its job, but I would suggest using the OnTerminate event on the thread. It is more 'Delphi natural' and the internal logic does the PostMessage bit for you. Since TThread is not a component, you can't view it in the object inspector and have to write and attach an event handler yourself. It gets called (in the main thread!) after the thread has completed/terminated.

While it looks okay, like jachguate I would use a bigger time-out value than 0 too. If you use WaitForSingleObject(MyThread.Handle, 100) then the main thread will wait a bit longer, thus eating up less CPU cycles.
A better solution would be the use of messages, though. Your application starts the thread and then puts all controls in disabled mode. The thread then executes and when it's finished, use SendMessage or PostMessage to the main window to notify it that the thread is done again. Then your application will just enable every control (and whatever else) again. This has as advantage that you keep the "natural" messageloop for the application alive, instead of running your own messageloop with this solution.
Unfortunately, the message-method has one drawback: if the thread crashes then no message will be sent back, so a backup plan would be practical. For example, by adding a timer control to your mainform which checks every second if the thread is still alive. If not, it too would just activate the form again, disabling itself again.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top