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!
thank you all for your comments/suggestions.
here i made a test app that has a timer routine that takes longer than the interval it is set for. when i push button1, Application.ProcessMessages hangs. my solution for now is to disable the timer during the timer routine.
later we plan to put the "device communications" in a thread.
thank you! mp
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
Timer1: TTimer;
Button1: TButton;
Memo1: TMemo;
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
memo1.Lines.Add('text 1');
// this call blocks
Application.ProcessMessages;
memo1.Lines.Add('text 2');
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
iTime:cardinal;
begin
// fix by adding this: timer1.Enabled:=false;
iTime:=GetTickCount;
while GetTickCount-iTime<200 do
;
// fix by adding this: timer1.Enabled:=true;
end;
end.
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 286
ClientWidth = 426
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 8
Top = 56
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 112
Top = 8
Width = 297
Height = 233
Lines.Strings = (
'Memo1')
TabOrder = 1
end
object Timer1: TTimer
Interval = 100
OnTimer = Timer1Timer
Left = 200
Top = 144
end