Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TTimer in a service?

1,704 views
Skip to first unread message

Jamie Dale

unread,
Apr 13, 2008, 6:57:58 PM4/13/08
to
Does TTimer actually work in a service?

I've got it in use in a TDataModule's OnCreate handler. The only line in the
handler is this:
Timer1.Enabled := True;

The timer never seems to fire. Why?

To test it, I also did it with a normal Win32 app and in the timer event I
set it to update a forms caption. It worked perfectly updating the form so
why won't it work as a service?

The very first line of the timer event is:
Utils.Log('log.txt', 'entering timer loop');

This line is never called, and I never find it in the log file.

What is going on? - This stupidly simple little program has been holding me
up for the last 4 hours and now it's really annoying me.

Please help.

JD


Hans-Peter Diettrich

unread,
Apr 13, 2008, 8:39:42 PM4/13/08
to
Jamie Dale wrote:

> I've got it in use in a TDataModule's OnCreate handler. The only line
> in the handler is this: Timer1.Enabled := True;
>
> The timer never seems to fire. Why?
>
> To test it, I also did it with a normal Win32 app and in the timer
> event I set it to update a forms caption. It worked perfectly
> updating the form so why won't it work as a service?

AFAIR the timer needs a HWND, in order to work, or a callback procedure.
No problem in an application, but in a service?

DoDi

Rob Kennedy

unread,
Apr 13, 2008, 10:02:57 PM4/13/08
to

TTimer creates its own window. But there also needs to be a message pump.

--
Rob

Jamie Dale

unread,
Apr 14, 2008, 3:00:41 AM4/14/08
to
So how do I get around this then?

I'm using uCiaService unit to make a normal app with a TDataModule work as a
service. I suppose I could instead use a normal Service Application but this
takes away my ability to have a .exe which can run standalone...

How can I create something to trigger my event outside of OnCreate?

Obviously I could call the main loop from OnCreate but then OnCreate would
never finish and I'm not really happy with this method.

What can I do?

Oh, one other thing, why is TTimer available on the component pallette if it
shouldn't be used in a TDataModule? :confused: (All other visual components
vanish)

JD
"Rob Kennedy" <m...@privacy.net> wrote in message
news:4802bb4f$1...@newsgroups.borland.com...

Jamie Dale

unread,
Apr 14, 2008, 4:32:38 AM4/14/08
to
Ok, I've just created a thread to do the work instead.

Same thing - Works fine as a win32 app, as soon as it runs as a service
NOTHING!!!

This is so frustrating - Can someone help please?

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:48030113$1...@newsgroups.borland.com...

Rabatscher Michael

unread,
Apr 14, 2008, 5:03:10 AM4/14/08
to
How about using a TEvent object and use the WaitFor method.
Signal the event in the OnStop routine.
Check the return value of this WaitFor method to determine if you
have either to call your function (on a timeout) or the finish the
thread (on a signal).

kind regards
Mike

Rob Kennedy

unread,
Apr 14, 2008, 10:12:08 AM4/14/08
to
Jamie Dale wrote:
> So how do I get around this then?
>
> I'm using uCiaService unit to make a normal app with a TDataModule work as a
> service. I suppose I could instead use a normal Service Application but this
> takes away my ability to have a .exe which can run standalone...
>
> How can I create something to trigger my event outside of OnCreate?
>
> Obviously I could call the main loop from OnCreate but then OnCreate would
> never finish and I'm not really happy with this method.
>
> What can I do?

I don't know. I've never written a service using Delphi's framework or
any other. My services have been written using only the API. What I
would do in your case is call CreateWaitableTimer and then incorporate
its handle into my existing calls to MsgWaitForMultipleObjects, where my
service waits for other things to trigger it to do work.

Someone else here can probably tell you whether there's already
something in a Delphi service where you can wait for handles to become
signaled. Rabatscher suggested using an event, so he probably knows.

> Oh, one other thing, why is TTimer available on the component pallette if it
> shouldn't be used in a TDataModule? :confused: (All other visual components
> vanish)

Who said it shouldn't be used in a data module? It descends from
TComponent but does not descend from TControl, so you can put it on a
data module just like you can any other component that fits that pattern.

--
Rob

Remy Lebeau (TeamB)

unread,
Apr 14, 2008, 1:13:49 PM4/14/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:48028ff2$1...@newsgroups.borland.com...

> The timer never seems to fire. Why?

What thread context are you creating the TDataModule in? TTimer is a
message-based timer. TTimer's constructor creates a hidden window to
receive WM_TIMER messages. As such, it needs an active message queue in
order to run correctly. If the OnTimer event is not firing, then you are
likely creating the TTimer instance in the context of a thread that does not
have a running message queue.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 14, 2008, 1:15:37 PM4/14/08
to

"Hans-Peter Diettrich" <DrDiet...@aol.com> wrote in message
news:4802a8d2$1...@newsgroups.borland.com...

> AFAIR the timer needs a HWND, in order to work

TTimer creates its own HWND internally.

> or a callback procedure.

You are referring to the SetTimer() API function, not the TTimer component.

Either way, however, requires a running message queue in order to receive
the WM_TIMER message that allows the OS to pass the message to the HWND, or
to trigger the specified callback.

> No problem in an application, but in a service?

TTimer can work in a service, but it requires extra work on your part to
make sure it is being used in the correct place within the service.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 14, 2008, 1:18:07 PM4/14/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:48030113$1...@newsgroups.borland.com...

> I'm using uCiaService unit to make a normal app with a TDataModule
> work as a service. I suppose I could instead use a normal Service
> Application but this takes away my ability to have a .exe which can
> run standalone...

You can use svCom for that.

> What can I do?

You must create the TDataModule (and thus TTimer) in the context of a thread
that has a running message queue.

> Oh, one other thing, why is TTimer available on the component
> pallette if it shouldn't be used in a TDataModule?

Because this problem has nothing to do with TDataModule. It has to do with
threading.

> All other visual components vanish

TDataModule is not a TWinControl descendant, so it cannot host visual
components. TTimer is not a TControl descendant, and thus is not a visual
component.


Gambit


Peter Below (TeamB)

unread,
Apr 14, 2008, 1:23:32 PM4/14/08
to
Jamie Dale wrote:

> What can I do?

Write a proper service instead of trying to shoehorn a UI app into a
service straightjacket. The services OnStart event (if you use the
standard service template that comes with Delphi) should create a
worker thread, the thread should create an instance of the datamodule
at the start of its Execute method and then enter a simple message
loop. This would allow the timer on the DM to operate. The services
OnStop event (as well as OnPause and OnContinue, if you intend to
support those) would send custom messages to the worker thread via
PostThreadMessage. The thread can process those in its message loop to
stop and restart the DMs timer and to terminate itself, if required. Do
*NOT* enable or disable the DM timer from any other thread!

> Oh, one other thing, why is TTimer available on the component
> pallette if it shouldn't be used in a TDataModule? :confused: (All
> other visual components vanish)

Oh, it is perfectly usable on a DM since it create its own internal
window. All it needs to operate is a message loop in the thread that
creates the DM instance.

--
Peter Below (TeamB)
Don't be a vampire (http://slash7.com/pages/vampires),
use the newsgroup archives :
http://www.tamaracka.com/search.htm
http://groups.google.com

Jamie Dale

unread,
Apr 14, 2008, 5:11:58 PM4/14/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:480390d6$3...@newsgroups.borland.com...

> What thread context are you creating the TDataModule in?

No idea. Initially the project (.dpr) source used uCiaService.CreateForm()
to create the TDataModule when installed as a service. The TTimer was on the
TDataModule.

Since then I've created a worker thread which is supposed to be created in
TDataModule.OnCreate. Thing is the thread only seems to work as a win32.exe
not a service.exe. It is so frustrating!!!

> TTimer is a message-based timer. TTimer's constructor creates a hidden
> window to receive WM_TIMER messages. As such, it needs an active message
> queue in order to run correctly.

Are we talking about Application.ProcessMessages ?

> If the OnTimer event is not firing, then you are likely creating the
> TTimer instance in the context of a thread that does not have a running
> message queue.

How do I find out?

Jamie Dale

unread,
Apr 14, 2008, 5:07:39 PM4/14/08
to
Don't suppose you could post a quick source sample? - Just something simple
I can build upon..


"Rabatscher Michael" <m.raba...@tom-medical.com> wrote in message
news:48031e2c$1...@newsgroups.borland.com...

Jamie Dale

unread,
Apr 14, 2008, 5:06:26 PM4/14/08
to

"Peter Below (TeamB)" <no...@nomail.please> wrote in message
news:xn0foxkr...@newsgroups.borland.com...

> Write a proper service instead of trying to shoehorn a UI app into a
> service straightjacket.

But you can't run a normal service.exe as a win32.exe - I'd like to have
both in one .exe

uCiaService has worked well for me with other simple projects in the past...

> Oh, it is perfectly usable on a DM since it create its own internal
> window. All it needs to operate is a message loop in the thread that
> creates the DM instance.

Are we talking about using Application.ProcessMessages ?


Jamie Dale

unread,
Apr 14, 2008, 5:03:12 PM4/14/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:480391db$1...@newsgroups.borland.com...

> You must create the TDataModule (and thus TTimer) in the context of a
> thread that has a running message queue.

Forgive me if I'm being thick here but... huh?

Whats all this message queue stuff about then and how do I know if I have
one or not?

Basically in my project source, uCiaService creates the TDataModule and then
uCiaService.Run

I've no idea about the message Queue - If you could explain I'd be grateful!

JD


Remy Lebeau (TeamB)

unread,
Apr 14, 2008, 6:07:00 PM4/14/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:4803c899$1...@newsgroups.borland.com...

> But you can't run a normal service.exe as a win32.exe -
> I'd like to have both in one .exe

Service .exes and non-service .exes use very different architectures. You
can't really have them in the same .exe file without using a framework
specifically designed for that. Even then, putting a UI into a service
would no longer work in Vista onwards anyway, so it makes more sense to keep
them separated.

> Are we talking about using Application.ProcessMessages ?

ProcessMessages() is the VCL's function for checking for pending messages at
that moment (in the main thread only - it is not very safe to use in worker
thread). It is not the actual message loop itself. That is inside of
Application.Run() instead.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 14, 2008, 6:02:57 PM4/14/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:4803c898$1...@newsgroups.borland.com...

> Whats all this message queue stuff about then

You do know what a message queue is in general, right? You can't do Win32
UI development without it.

> how do I know if I have one or not?

The main thread in any VCL app has a message queue. So does the worker
thread that TService creates internally to handle SCM requests. Any other
thread does not have a message queue unless its code creates one manually.

> Basically in my project source, uCiaService creates the TDataModule
> and then uCiaService.Run

I have no idea what uCiaService is or what it does internally.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 14, 2008, 6:10:05 PM4/14/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:4803c89a$2...@newsgroups.borland.com...

> No idea.

Then I suggest you read up on how multi-threaded programming works in
general, and how the Win32 API uses message loops.

> Initially the project (.dpr) source used uCiaService.CreateForm()
> to create the TDataModule when installed as a service.
> The TTimer was on the TDataModule.

Then the TDataModule, and thus its TTimer, is being created in the context
of the main thread. All WM_TIMER messages for the TTimer will be received
by the main thread's message loop, if it has one. I have no clue how
uCiaService is implemented, so I have no clue if it even starts a message
loop. Since your TTimer is not working, then it stands to reason that
uCiaService is not running a message loop.


Gambit


Rabatscher Michael

unread,
Apr 15, 2008, 10:59:03 AM4/15/08
to
Basically I would use the following code (it's far from complete since
some events (Pause, continue...) are missing but it shows the basic
principle):

procedure TService1.ServiceCreate(Sender: TObject);
begin
fSignal := TSimpleEvent.Create;
end;

procedure TService1.ServiceDestroy(Sender: TObject);
begin
FreeAndNil(fSignal);
end;

procedure TService1.ServiceExecute(Sender: TService);
begin
while fSignal.WaitFor(500) = wrTimeout do
begin
// execute code here
end;
end;

procedure TService1.ServiceShutdown(Sender: TService);
begin
fSignal.SetEvent;
end;

Remy Lebeau (TeamB)

unread,
Apr 15, 2008, 12:44:49 PM4/15/08
to

"Rabatscher Michael" <m.raba...@tom-medical.com> wrote in message
news:4804c317$1...@newsgroups.borland.com...

> procedure TService1.ServiceCreate(Sender: TObject);
> begin
> fSignal := TSimpleEvent.Create;
> end;
>
> procedure TService1.ServiceDestroy(Sender: TObject);
> begin
> FreeAndNil(fSignal);
> end;

Rather than using the OnCreate/Destroy events, I would suggest using the
OnStart/Stop/Shutdown events instead. That way, the TSimpleEvent is
instantiated only when the service is actually running. OnCreate/Destroy
are always called, whether the service is being installed/uninstalled or is
running.


Gambit


Peter Below (TeamB)

unread,
Apr 15, 2008, 12:58:52 PM4/15/08
to
Jamie Dale wrote:

No, that function may do other things in addition to what you need and
it also does not wait for messages to come in, it returns immediately
when there is no message to process. For a thread that is controlled by
messages that is not optimal. A secndary threads message loop would be
something like

var
Msg: TMsg;
res: Integer;
begin
While not terminated Do Begin
res := Integer( GetMessage(Msg, 0, 0, 0 ));
If res = -1 Then
terminate // error
else if res = 0 then
terminate // WM_QUIT received
else
DispatchMessage( Msg );
End; { While }

You would either put this into the threads Execute method or in a
method you call from Execute.

The declaration of GetMessage is typcially MS schizophrenic: they
declare it as BOOL but in fact require you to handle *three* return
conditions. Go figure... Note that the thread will be suspended in
GetMessage until it actually gets a message. To close it down you need
to send it a WM_QUIT message (via PostThreadMessage, for instance), or
call its Terminate method *and* send it any other message (even a
WM_NULL will do). Use the Thread.Handle as first parameter to
PostThreadMessage.

Remy Lebeau (TeamB)

unread,
Apr 15, 2008, 2:36:03 PM4/15/08
to

"Peter Below (TeamB)" <no...@nomail.please> wrote in message
news:xn0foyyq...@newsgroups.borland.com...

> While not terminated Do Begin
> res := Integer( GetMessage(Msg, 0, 0, 0 ));

Since GetMessage() waits for a message to arrive, I would suggest using
PeekMessage() or MsgWaitForMultipleObjects() instead.


Gambit


Jamie Dale

unread,
Apr 15, 2008, 4:45:43 PM4/15/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:4803d648$1...@newsgroups.borland.com...

> I have no clue how uCiaService is implemented, so I have no clue if it
> even starts a message loop.

Hi Remy, below is the entire source unit for uCiaService - Can you advise if
it starts a message queue?:

unit uCiaServiceTools;

interface

uses

SysUtils, Classes, Windows, SvcMgr, WinSvc;

type

TCiaService = class(TService)

protected

procedure Start(Sender: TService; var Started: boolean);

procedure Stop(Sender: TService; var Stopped: boolean);

procedure Execute(Sender: TService);

public

function GetServiceController: TServiceController; override;

constructor CreateNew(AOwner: TComponent; Dummy: integer = 0); override;

procedure CreateForm(InstanceClass: TComponentClass; var Reference);

procedure Run;

end;

function CiaStartService(DisplayName: string): Boolean;

function CiaIsService: boolean;

var

CiaService: TCiaService;

implementation

var

FIsService: boolean;

FServiceName: string;

FDisplayName: string;

//------------------------------------------------------------------------------

//----
TCiaService -------------------------------------------------------------

//------------------------------------------------------------------------------

procedure ServiceController(CtrlCode: dword); stdcall;

begin

CiaService.Controller(CtrlCode);

end;

//------------------------------------------------------------------------------

function TCiaService.GetServiceController: TServiceController;

begin

result := ServiceController;

end;

//------------------------------------------------------------------------------

procedure TCiaService.CreateForm(InstanceClass: TComponentClass; var
Reference);

begin

SvcMgr.Application.CreateForm(InstanceClass, Reference);

end;

//------------------------------------------------------------------------------

procedure TCiaService.Run;

begin

SvcMgr.Application.Run;

end;

//------------------------------------------------------------------------------

constructor TCiaService.CreateNew(AOwner: TComponent; Dummy: integer);

begin

inherited;

AllowPause := False;

Interactive := True;

DisplayName := FDisplayName;

Name := FServiceName;

OnStart := Start;

OnStop := Stop;

end;

//------------------------------------------------------------------------------

procedure TCiaService.Start(Sender: TService; var Started: boolean);

begin

Started := True;

end;

//------------------------------------------------------------------------------

procedure TCiaService.Execute(Sender: TService);

begin

while not Terminated do

ServiceThread.ProcessRequests(True);

end;

//------------------------------------------------------------------------------

procedure TCiaService.Stop(Sender: TService; var Stopped: boolean);

begin

Stopped := True;

end;

//------------------------------------------------------------------------------

//----
Various -----------------------------------------------------------------

//------------------------------------------------------------------------------

function CiaIsService: boolean;

begin

Result := FIsService;

end;

//------------------------------------------------------------------------------

function CiaStartService(DisplayName: string): Boolean;

var

Mgr, Svc: Integer;

UserName, ServiceStartName: string;

Config: Pointer;

Size: DWord;

n: integer;

begin

FDisplayName := DisplayName;

FServiceName := DisplayName;

for n := 1 to Length(FServiceName) do

if FServiceName[n] = ' ' then

FServiceName[n] := '_';

FIsService := FindCmdLineSwitch('install', ['-','\','/'], True) or

FindCmdLineSwitch('uninstall', ['-','\','/'], True);

if FIsService then begin

SvcMgr.Application.Initialize;

CiaService := TCiaService.CreateNew(SvcMgr.Application, 0);

Result := True;

Exit;

end;

Mgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);

if Mgr <> 0 then begin

Svc := OpenService(Mgr, PChar(FServiceName), SERVICE_ALL_ACCESS);

FIsService := Svc <> 0;

if FIsService then begin

QueryServiceConfig (Svc, nil, 0, Size);

Config := AllocMem(Size);

try

QueryServiceConfig(Svc, Config, Size, Size);

ServiceStartName := PQueryServiceConfig(Config)^.lpServiceStartName;

if CompareText(ServiceStartName, 'LocalSystem') = 0 then

ServiceStartName := 'SYSTEM';

finally

Dispose(Config);

end;

CloseServiceHandle(Svc);

end;

CloseServiceHandle(Mgr);

end;

if FIsService then begin

Size := 256;

SetLength(UserName, Size);

GetUserName(PChar(UserName), Size);

SetLength(UserName, StrLen(PChar(UserName)));

FIsService := CompareText(UserName, ServiceStartName) = 0;

end;

Result := FIsService;

if FIsService then begin

SvcMgr.Application.Initialize;

CiaService := TCiaService.CreateNew(SvcMgr.Application, 0);

end;

end;

end.


Jamie Dale

unread,
Apr 15, 2008, 4:48:12 PM4/15/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:4803d58e$1...@newsgroups.borland.com...

> It is not the actual message loop itself. That is inside of
> Application.Run() instead.

uCiaService uses this in uCiaService.Run:

procedure TCiaService.Run;

begin

SvcMgr.Application.Run;

end;

Does that help?


Jamie Dale

unread,
Apr 15, 2008, 4:52:51 PM4/15/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:4803d49d$1...@newsgroups.borland.com...

>
> "Jamie Dale" <jamie...@yahoo.com> wrote in message
> news:4803c898$1...@newsgroups.borland.com...
>
>> Whats all this message queue stuff about then
>
> You do know what a message queue is in general, right? You can't do Win32
> UI development without it.

Yeah it handles windows messages - EG mousedown and onclose etc right? For
some reason when I first queried it I didn't put 2 & 2 together (i was a bit
slow last night)

>> how do I know if I have one or not?
>
> The main thread in any VCL app has a message queue. So does the worker
> thread that TService creates internally to handle SCM requests. Any other
> thread does not have a message queue unless its code creates one manually.

Problem is that when I found TTimer wouldn't work, I copied the code into a
seperate thread which did not use a TTimer but a repeat/until loop instead.
In this loop, idIcmpClient is set to ping every ip in a certain range on my
network to check if it is online - if not it shuts down the system it is
running on. Problem is the loop doesn't seem to run - without the TTimer!

It really is frustrating...


Jamie Dale

unread,
Apr 15, 2008, 4:57:51 PM4/15/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:4803d648$1...@newsgroups.borland.com...

>
> "Jamie Dale" <jamie...@yahoo.com> wrote in message
> news:4803c89a$2...@newsgroups.borland.com...
>
>> No idea.
>
> Then I suggest you read up on how multi-threaded programming works in
> general, and how the Win32 API uses message loops.

Yeah probably right! I got the Delphi 6 Dev Guide but the sheer size of it
is rather off putting... Add to that my total lack of spare time these days
andit isn't really surprising I'm not learning much :(


>
>> Initially the project (.dpr) source used uCiaService.CreateForm()
>> to create the TDataModule when installed as a service.
>> The TTimer was on the TDataModule.
>
> Then the TDataModule, and thus its TTimer, is being created in the context
> of the main thread.

So theoretically IF uCiaService was doing things correctly a message queue
would be in place... Thats IF though..

> All WM_TIMER messages for the TTimer will be received by the main
> thread's message loop, if it has one.

So it probably doesn't... Damn..

> I have no clue how uCiaService is implemented, so I have no clue if it
> even starts a message loop.

I posted the source in a seperate reply - If you could spare a few mins to
take a look I'd be very grateful.

JD


Remy Lebeau (TeamB)

unread,
Apr 15, 2008, 5:58:18 PM4/15/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:4805159d$1...@newsgroups.borland.com...

> Yeah it handles windows messages - EG mousedown and onclose etc right?

Yes, amongst many others.

> Problem is that when I found TTimer wouldn't work, I copied
> the code into a seperate thread which did not use a TTimer but
> a repeat/until loop instead. In this loop, idIcmpClient is set to
> ping every ip in a certain range on my network to check if it is
> online - if not it shuts down the system it is running on. Problem
> is the loop doesn't seem to run - without the TTimer!

Then your code is probably deadlocking itself.


Gambit


Remy Lebeau (TeamB)

unread,
Apr 15, 2008, 6:01:40 PM4/15/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:4805...@newsgroups.borland.com...

> Hi Remy, below is the entire source unit for uCiaService -
> Can you advise if it starts a message queue?:

Yes, it does, for the thread that calls Run().


Gambit


Jamie Dale

unread,
Apr 16, 2008, 1:43:01 AM4/16/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:480525c7$1...@newsgroups.borland.com...

So what could I be doing wrong? - The code runs fine as Win32 but not as a
service!

If it has a message queue then it should be fine right?

I'm definately having a bad week...


Remy Lebeau (TeamB)

unread,
Apr 16, 2008, 12:48:40 PM4/16/08
to

"Jamie Dale" <jamie...@yahoo.com> wrote in message
news:4805...@newsgroups.borland.com...

> So what could I be doing wrong? - The code runs fine as Win32 but not as a
> service!

Since the TTimer is being created in the context of the main thread, and
ciaService is running a message loop in the context of the main thread, the
only way the TTimer::OnTimer event would not work is if either the
TTimer::Enabled property is false, or something else in your project is
swallowing WM_TIMER messages before TTimer can receive them.


Gambit


Peter Below (TeamB)

unread,
Apr 16, 2008, 1:11:56 PM4/16/08
to
Remy Lebeau (TeamB) wrote:

It is intended to wait, for a message-driven thread that is a proper
design, IMO. Why implement a separate wait mechanism if Windows
supplies one?

Remy Lebeau (TeamB)

unread,
Apr 16, 2008, 4:45:25 PM4/16/08
to

"Peter Below (TeamB)" <no...@nomail.please> wrote in message
news:xn0fp0dm...@newsgroups.borland.com...

> It is intended to wait, for a message-driven thread that is
> a proper design, IMO. Why implement a separate wait
> mechanism if Windows supplies one?

If you were waiting on only a message, that would be fine. But you are
having to post a message to wake up the thread in order to handle the
Terminated property in a timely manner as well. So the thread could just
timeout its waiting periodically to check that without having to post
anything.


Gambit


Jamie Dale

unread,
Apr 16, 2008, 5:41:52 PM4/16/08
to

"Remy Lebeau (TeamB)" <no....@no.spam.com> wrote in message
news:4806...@newsgroups.borland.com...

> the only way the TTimer::OnTimer event would not work is if either the
> TTimer::Enabled property is false, or something else in your project is
> swallowing WM_TIMER messages before TTimer can receive them.

Timer.Enabled := True; - I coded the line in specifically to make sure that
i wasn't relying on the default enabled property.

So, I guess that leaves only the 2nd suggestion - something swallowing the
WM_TIMER messages. What could this be? - Any ideas?


0 new messages