Fog Creek Software
Discussion Board




Application.ProcessMessage within Thread

I am writing a high production Delphi application that outputs graphics to Multiple Printers. Each printer will be controlled by its own Application thread.
  Approx every three seconds I will output to each printer, and then either suspend the thread for a couple seconds or monitor the printer in a loop within each thread that contains an Application.ProcessMessages() after checking the status of each printer.  Whenever the Printer status indicates it has finished a Page, I will output another page.
  Question: Does Application.ProcessMessages() within a thread transfer control to other threads similar to a Suspend(), or should I use sleep(50), or should I Suspend the thread, and then have a WatchDog timer reawaken  each suspended Thread every 3 seconds?
  I'm familiar with both Application.ProcessMessages(0 and sleep() in a Delphi program that has only the main VCL thread, but am ignorant about these Calls within multiple Threads.... Many thanks for any help.

 

James Eric Anderson
Saturday, December 07, 2002

Hi James,

I am a big confused; the 'Application' is singleton - there only ever is one.

What you can do is subclass the TThread class to give you a separate thread for each printer.

Generally, if the graphics are known at the time the thread is started, there is no need to use sleeping or anything.  If you want to send commands to the printers etc, you need to start communicating between threads; this can be done with simple global variables (e.g. a boolean flag), but for anything bigger than an integer (e.g. strings, records, complex things) you will need to implement a queue of commands (look at TThreadList).  The term to check is "thread safe".

Nice
Monday, December 09, 2002

Application.Processmessages will interupt execution of whatever the application main thread is doing and give control to the message queue. Like Nice says there's only one application thread. It's the one that controls the windows message queue.

Use sleep(0) if you created your own threads and want to interupt it to let other threads use the remaining time slice. But generally the OS will handle time slices pretty well.

Looking at your problem there's probably an easier solution. Fire off the print jobs from your application main thread and use Ttimers to monitor printer statuses. If creating a print jobs takes a lot of time you probably do want to create a print queue thread to keep the application responsive. To learn more about threads in Delphi you might want to read this article:

http://www.pergolesi.demon.co.uk/prog/threads/ToC.html

Jan Derk
Monday, December 09, 2002

Does the printer send any windows messages to report its status? If so, you can have your thread wait using the MsgWaitForMultipleObjects() function. Basically, you need to create a TEvent object. When you want your thread to pause, call MsgWaitForMultipleObjects() passing in the TEvent object as a parameter. This will cause your thread to pause until someone signals the event object (e.g. you may want to do this from the main thread). The beauty of MsgWaitForMultipleObjects() is that not only does it wait until the event object is signalled, but it will also return if any windows messages are posted to your thread's message queue. The return value of MsgWaitForMultipleObjects() gives you some context as to why it stopped waiting (event was signalled, windows message, timeout etc.)

I have used this approach so that a worker thread can do some work at regular intervals. I create a timer and call MsgWaitForMultipleObjects() with a parameter telling it I want to be "woken up" on TIMER messages. When the thread wakes up, it does its work then goes back to sleep until the next TIMER message. If you want sample code for this, send me e-mail and I'll get it to you.

Also, I'd like to comment on Application.ProcessMessages. It is my understanding that it arranges to have all queued messages processed, including those that were posted to your thread, which get processed by your thread, not by the main thread. Does anybody know if this is correct?

Bryan Bedard
Thursday, December 12, 2002

Yes, you are right. Processmessages does process all application messages in the queue including those from threads. I was talking bollocks.

Jan Derk

Jan Derk
Thursday, December 12, 2002

Use Sleep. You don't wanna mess with a VCL method like
Application.ProcessMessages unless you call it from a Synchronized procedure.

Sleep will relinquish control to other system threads,
including your app's main thread.

Calling Sleep(dwMilliseconds) also gives you more precise
control over just how much time your thread waits, whereas
Application.ProcessMessages is kinda like saying to the app
thread "whenever you're ready..."

Tinashe Rondozai
Saturday, December 21, 2002

*  Recent Topics

*  Fog Creek Home