Solved

ServiceStop doesn't execute!!

Posted on 2003-12-03
26
365 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

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…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

734 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