Solved

ServiceStop doesn't execute!!

Posted on 2003-12-03
26
363 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
ID: 9866336
drop some application.processmessages-lines
into your onTimer-event

just a guess

meikl ;-)
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 9866683
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
ID: 9866722
listening...

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

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


0
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 

Author Comment

by:roburobe
ID: 9866779
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
ID: 9866865
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
ID: 9866951
And what about creating another timer that makes Service.ServiceThread.ProcessRequests every 1/2 second?
0
 

Author Comment

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

Expert Comment

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

Expert Comment

by:bpana
ID: 9866990
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
ID: 9874916
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
ID: 9875307
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
 
LVL 17

Expert Comment

by:geobul
ID: 9875375
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
ID: 9875440
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
ID: 9875447
Ferruccio68, what do you think about it?
0
 
LVL 22

Assisted Solution

by:Ferruccio Accalai
Ferruccio Accalai earned 250 total points
ID: 9899831
-> 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
ID: 9899940
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
ID: 9911046
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
ID: 9911380
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
ID: 10711530
just wondering about the accepted answer with 0 (zero) points?
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 10711623
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
ID: 10711647
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
ID: 10711681
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
ID: 10711803
If you can, please, so I can adjust my solution.....

thank you very much!!!!

Roberto
0

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SUM 2 INTEGER ARRAYS INTO 1 10 100
Firemonkey webbrowser scrollbars ? 1 38
Multi-layered image in FireMonkey 9 31
enhance the following code 3 30
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

785 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