Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Application.ProcessMessages hangs?

my single threaded delphi 2009 app (not quite yet complete) has started to have a problem with Application.ProcessMessages hanging. my app has a TTimer object that fires every 100 ms to poll an external device. i use Application.ProcessMessages to update the screen when something changes so the app is still responsive.

one of these was in a grid OnMouseDown event. in there, it had an Application.ProcessMessages that essentially hung. removing that was no problem except that i soon discovered another Application.ProcessMessages that was also blocking.

i think what may be happening to me is that the TTimer is--in the app mode i'm currently debugging--probably taking too long to complete. i have prevented the TTimer.OnTimer event hander from re-entering the same code (see below):

procedure TfrmMeas.tmrCheckTimer(Sender: TObject);
begin
  if m_CheckTimerBusy then
    exit;

  m_CheckTimerBusy:=true;
  try
    PollForAndShowMeasurements;
  finally
    m_CheckTimerBusy:=false;
  end;
end;

what places would it be a bad practice to call Application.ProcessMessages? OnPaint routines springs to mind as something that wouldn't make sense.

any general recommendations?

i am surprised to see this kind of problem arise at this point in the development!


1 Answers

My recommendation regarding TApplication.ProcessMessages is to never ever use it - there simply isn't a good point to place it.

Imagine what calling it does: your application runs a message loop - where the windows messages (produced by OS, other apps, your app etc) are sequentially processed - and there, in the middle of one of the message-processings, you just re-run the whole message loop again, without having control over what messages will be processed, how much of them there will be, if any of the messages will enter its' own message loop... and if they have any reentrancy problems or not. That's what I call inviting trouble.

There are sometimes good reasons to process some windows messages (particularry to not hang other threads), or to process all messagess directed to a particular window, but this may be accomplished in more subtle ways, with more control.

If you have to do any processing in the main GUI thread, and you just want to update the interface, you may use the TWinControl.Repaint method to redraw the GUI elements.
If you want to keep the app responsive to user input, you basically have to use backgroud/worker threads.

Notice: in Delphi, while doing any lenghty processing in the main thread, especcially if waiting is involved, you are supposed to call CheckSynchronize periodically, to allow any other threads to synchonize with the main thread - they may (and probably will) hang otherwise.
VCL calls this only when the app goes idle and when it processes the WM_NULL message (that is supossed to do nothing, which may cause some interesting side-effects too).

like image 59
Viktor Svub Avatar answered Jul 06 '26 05:07

Viktor Svub



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!