Solved

ServiceStop doesn't execute!!

Posted on 2003-12-03
26
360 Views
Last Modified: 2010-04-05
Hello everybody

I built a Service with Delphi5.
In this service, I create a TTimer at runtime and this TTimer, in the OnTimer event does some job.
My problem is that if I try to stop the service when the Job is running, the ServiceStop event handler doesn't exec. It execs at the end of the job. If I stop the service while the timer is waiting, the ServiceStop eventhandler runs immediately.
What can I do?

Thanks to everybody!!!

Roberto
0
Comment
Question by:roburobe
  • 8
  • 4
  • 4
  • +3
26 Comments
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
drop some application.processmessages-lines
into your onTimer-event

just a guess

meikl ;-)
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
Comment Utility
Well, meikl suggestion is the more easy and it should work good.
BTW, in a Service application, i'd create a TThread instead of using a TTimer, and let do the job by the TThread...

F68 ;-)
0
 
LVL 2

Expert Comment

by:classmate
Comment Utility
listening...

meikl:
>drop some application.processmessages-lines...

TServiceApplication does not have a processmessages method in my delphi edition (D6)


0
 

Author Comment

by:roburobe
Comment Utility
classmate is right. a TService hasn't a ProcessMessages method.
I can write Service.ServiceThread.ProcessRequests but is it the same thing?

Thanks
0
 
LVL 6

Expert Comment

by:bpana
Comment Utility
hi,

being a service application you cannot use application.processmessages.

When you stop the service, I suppose that it sends a message to your service to stop. I suppose that you have to intercept that message into your code, and exit the curent procedure.

Bogdan
0
 

Author Comment

by:roburobe
Comment Utility
And what about creating another timer that makes Service.ServiceThread.ProcessRequests every 1/2 second?
0
 

Author Comment

by:roburobe
Comment Utility
I already done that timer but it doesn't work..... :-(
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
>TServiceApplication does not have a processmessages method
ooops, sorry, not thought on that, its a service ;-)
0
 
LVL 6

Expert Comment

by:bpana
Comment Utility
normally, you should use the onExecute event, which should look like this:

procedure TService1.ServiceExecute(Sender: TService);
begin
  // init...
 while not Terminated do
    ServiceThread.ProcessRequests(True);// wait for termination
  // exit...
end;

Bogdan
0
 
LVL 17

Expert Comment

by:geobul
Comment Utility
Hi,

Try this: add lines in your OnTimer event like:

procedure TService1.Timer1Timer(Sender: TObject);
var i: integer;
begin
 if not Terminated then begin
   // one interruptable part of the code
 end else exit;
 if not Terminated then begin
   // another interruptable part of the code
 end else exit;
 // etc.
 // or you have a loop
 for i := 0 to 1000000 do begin
   if not Terminated then begin
     // the loop body
   end else exit;
 end;
end;

Regards, Geo
0
 

Author Comment

by:roburobe
Comment Utility
Geo, this would be a nice solution. My problem is that in my OnTimer Event I call a procedure and that procedure calls many other procs in a structured mode. So I can't split the code.
I think one solution should be Ferruccio68's one. But before beginning such a transformation, I'd like to wait some more.

Thank you very much
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 17

Expert Comment

by:geobul
Comment Utility
I don't think that moving your procedure call from the timer into a thread will solve your problem. It will simply move the termination problem in the thread and you'll have to find a way of terminating that thread. You'll need to divide your code in parts in that case also and to check for TThread.Terminated instead. Please, correct me if I'm wrong.
0
 

Author Comment

by:roburobe
Comment Utility
Could be. the TTimer has his own thread so it should be the same thing.....

But in my code I have a point that is passed frequently. There I added the ckeck for Terminated but without results. I will try again payin' more attention.

Thank you very much.

Roberto
0
 

Author Comment

by:roburobe
Comment Utility
Ferruccio68, what do you think about it?
0
 
LVL 22

Assisted Solution

by:Ferruccio Accalai
Ferruccio Accalai earned 250 total points
Comment Utility
-> My problem is that in my OnTimer Event I call a procedure and that procedure calls many other procs in a structured mode. So I can't split the code.

well i think the difference between TTimer and TThread is this:

In Ontimer let's say you call DoProcerdures where DoProcedures is about

procedure DoProcedures;
begin
   DoFirstProc;
   DoSecondProc;
   DoThirdProc;
   etc...etc...
end;

So in your ontimer you must wait the whole execution of DoProcedures....

Using a TThread you can skip the DOProcedures one and let do the job by it like;

procedure TMyThrade.Execute;
begin
  while not Terminated do
  begin
   DoFirstProc;
   DoSecondProc;
   DoThirdProc;
   etc...etc...
  end;
end;
This means that the check for Terminated is done at the end of every single procedure....
BTW i was meaning that working in a Service i usually prefere to put my biggest procedures into threads so i can pass the Service stop into the thread directly and terminate the active thread at that time...

Note that using several threads could consume CPU times...but can give you the possibility of let execute Threads also if one thread is performing and waiting a slow execution...

F68 ;-)



0
 
LVL 6

Expert Comment

by:bpana
Comment Utility
roburobe,

btw, why do you use a windows servcice for this task?

as i suppose, a Windows Service should provide its service (services) to other applications.

using a timer in a windows service is like making a formless application and schedule it.

just curious ...

Bogdan
0
 
LVL 17

Accepted Solution

by:
geobul earned 250 total points
Comment Utility
Hi,

I'm sorry for saying that but you must explicitly check the Terminated property before every procedure in order to get it stopped. Just as I said that before:

procedure TMyThrade.Execute;
begin
  while not Terminated do
  begin
    if not Terminated then DoFirstProc;
    if not Terminated then DoSecondProc;
    if not Terminated then DoThirdProc;
    etc...etc...
  end;
end;

You may check that the thread's terminated status has been checked once only in a loop of the type:

while not Terminated do        // here is the check only and the body is interruptable !!!
  begin
   DoFirstProc;
   DoSecondProc;
   DoThirdProc;
   etc...etc...
  end;

using the example below. Start the thread and press Stop button after 'Line 1'. The thread will show all five lines before it gets terminated:

type
  TForm1 = class(TForm)
    re: TRichEdit;
    btnCreateThread: TButton;
    btnTerminateThread: TButton;
    procedure btnTerminateThreadClick(Sender: TObject);
    procedure btnCreateThreadClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TTransactionThread = class(TThread)
    procedure Execute; override;
    procedure Oops;
  private
    c: string;
  end;

var
  Form1: TForm1;
  TransactionThread: TTransactionThread;

implementation

{$R *.DFM}

procedure TTransactionThread.Oops;
begin
  Form1.re.Lines.Add('Line '+c);
end;

procedure TTransactionThread.Execute;
begin
 while (not terminated) do begin
   c := '1';
   Synchronize(Oops);
   sleep(1000);
   c := '2';
   Synchronize(Oops);
   sleep(1000);
   c := '3';
   Synchronize(Oops);
   sleep(1000);
   c := '4';
   Synchronize(Oops);
   sleep(1000);
   c := '5';
   Synchronize(Oops);
   sleep(1000);
 end;
end;

procedure TForm1.btnTerminateThreadClick(Sender: TObject);
begin
  TransactionThread.Terminate;
end;

procedure TForm1.btnCreateThreadClick(Sender: TObject);
begin
  TransactionThread := TTransactionThread.Create(true);
  TransactionThread.FreeOnTerminate := true;
  TransactionThread.Resume;
end;

end.

Regards, Geo
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
Comment Utility
geobul you're absolutelly right....my mistake in my previous post (it came just from head :) BTW your example is quit near to what i was meaining...

F68 ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
just wondering about the accepted answer with 0 (zero) points?
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
Comment Utility
Hi meikl, i've received an assisted with B grade for 750 total points and i guess that's the same for Geo....
I don't know about the sense of accepting and assisting used by the questioner here, but if for some mistake you've to reopen the question, as you're the PE, for me it's ok :)

F68 ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
Comment Utility
just waiting for the questioner's intention.

btw.
i'm not worry about 0 pts., still wondering,
so i may ask the questioner, if the grading is so
ok as he/she meant .

meikl ;-)
0
 

Author Comment

by:roburobe
Comment Utility
Hello,

I made a mistake... I didn't click any "radio button" fro the accepted answer and then EE assigned meikl's answer to be my accepted answer. I intended to spit points between F68 and Geobul with Geobul to be the answerer.
So:
1) please, don't worry... I'm not an expert like you....
2) can tuo help me solve this situation???

Thank you very much!!!

Roberto
0
 

Author Comment

by:roburobe
Comment Utility
If you can, please, so I can adjust my solution.....

thank you very much!!!!

Roberto
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now