2

I have a message queue based on a thread that processes messages being thrown at it. As some activities in the thread may be VCL commands they are performed in Synchronize. As soon Synchronize is called the thread hangs. Sample code:

TMessageQ = class (TThread)
...
procedure TMessageQ.do_msg;
begin
   case CurrentMessage.Command of
      cQSize:  if Assigned (OnSize)  then OnSize  (CurrentMessage);
      cQReady: if Assigned (OnReady) then OnReady (CurrentMessage);
   end; // case
end; // do_msg /

procedure TMessageQ.doTask (Sender: TObject);
begin
   while FQ.Count > 0 do
   begin
      FSection.Enter;
      try
         CurrentMessage := FQ.Dequeue;
      finally
         FSection.Leave;
      end; // try..finally
      Synchronize (do_msg);
   end; // while
end; // doTask //

No statement in do_msg is ever being processed. Does somebody know what I am doing wrong?

Arnold
  • 4,578
  • 6
  • 52
  • 91
  • 4
    What is happening in the Main thread? Synchronize needs the MessageLoop. If the main thread is waiting for this one then it would figure. – H H Apr 26 '12 at 20:53
  • 4
    +1 for Hank - identifying the #1 reason for dead Delphi apps - TThread.Synchronize and, (probably), TThread.WaitFor(). Like Hank says, whatever you are doing in your GUI thread, stop doing it, exit the event-handler and resume processing messages. If, at this stage, the phrase 'Application.ProcessMessages' is going through your brain - purge it :) – Martin James Apr 26 '12 at 21:03
  • I am afraid you are right (see comemnt below). And thank you for warning against Application.ProcessMessages :-). I'll test this in the evening. – Arnold Apr 27 '12 at 05:09
  • yes, you were right. See my comment at remy's answer. – Arnold Apr 27 '12 at 18:36

1 Answers1

4

TThread.Synchronize() blocks until the main thread processes the request. The main thread requires an active message loop in order to process requests (unless you manually call Application.ProcessMessages() or CheckSynchronize() periodically). If your thread's main work is always being invoked by TThread.Synchronize(), there is no point in using a thread at all. You could just use a timer or custom window message in the main thread instead and take out all of the unnecessary complexity.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I am afraid it will be as simple as this, my main thread continues. I'll check this out and come back. – Arnold Apr 27 '12 at 05:07
  • You (and Henk and Martin) were right. I was using the main thread as a kind of timer to determine how long a certain task lasted. I use a thread here because I have two different processes. In one process something happens, another (asynchronously) handles the outcome. In http://stackoverflow.com/questions/9033860/reduce-cpu-time-spent-in-vcl it was suggested to use two threads to separate CPU-hungry and not so CPU-hungry tasks. A thread in this case is more complex, but I need not think when to process the messages. A thread sometimes simplifies things as long as you keep it simple. – Arnold Apr 27 '12 at 18:35