delphi服务应用程序在15秒后停止,计时器不执行

时间:2012-09-15 12:15:44

标签: delphi service timer

我想在Delphi中制作服务应用程序,每天下午02:00运行并复制一些文件。所以我用过计时器。但控制不会进入计时器事件,服务会在15秒内终止。我在Timer Event上写了一段代码。我怎样才能使用定时服务?请帮忙。在此先感谢。

我的代码就在这里:

unit untMain;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.SvcMgr, Vcl.Dialogs, Vcl.ExtCtrls, DateUtils, Vcl.Forms,
untCommon;

type
TsrvBackupService = class(TService)
tmrCopy: TTimer;
procedure tmrCopyTimer(Sender: TObject);

private
strlstFiles : TStringList;
{ Private declarations }
public
{ Public declarations }
end;

var
srvBackupService: TsrvBackupService;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
srvBackupService.Controller(CtrlCode);
end;


procedure TsrvBackupService.tmrCopyTimer(Sender: TObject);
var
strCurTime   : string;
strBKPpath   : string;
strBKPTime   : string;
NowDay       : word;
NowMonth     : word;
NowYear      : word;
NowHour      : word;
NowMin       : word;
NowSec       : word;
NowMilli     : Word;
begin
  DecodeTime(now,NowHour,NowMin,NowSec,NowMilli);
  strCurTime := IntToStr(NowHour)+':'+IntToStr(NowMin);
  strBKPTime := '14:00'
  strBKPpath := ExtractFilePath(Application.ExeName);
  if strCurTime = strBKPTime then begin
     Try
           CopyFile(PChar('c:\datafile.doc'),PChar(strBKPpath + 'datafile.doc'),true);
     except
        on l_e: exception do begin
           MessageDlg(l_E.Message,mtError,[mbOk],0);
        end;
     end;
  end;
end;

end.

3 个答案:

答案 0 :(得分:6)

使用在OnStart事件中启动的简单线程,而不是计时器。

教程在这里:

http://www.tolderlund.eu/delphi/service/service.htm

TTimer更适合GUI应用程序。他们需要一个消息泵(参见here):

  

TTimer需要一个正在运行的消息队列才能接收   WM_TIMER消息,允许操作系统将消息传递给HWND,   或触发指定的回调

答案 1 :(得分:1)

正如其他人所解释的那样,你不能简单地在Windows服务应用程序中使用TTimer组件,因为它依赖于默认情况下在服务中没有出现的消息泵。我看到四个主要选择:

  1. 实施message pump以便能够使用TTimer
  2. 使用Thread不断检查日期/时间
  3. 与#2一样,使用服务OnExecute event检查日期/时间
  4. 使用Windows“Scheduled Tasks
  5. 我会推荐上面的#2,这就是原因。

    #1对你的场景可能有点多,我相信你不想走那么远。

    #3可能更容易,但服务的线程需要一些特殊的处理,我也确定你不需要关心。

    #4可能是理想的解决方案,但我不会尝试更改您对服务的决定。

    创建线程是一种可行的方法,因为它非常简单且可扩展。我的所有服务应用程序都在多线程的基础上工作,除了处理实际服务之外,什么都没有进入实际服务的线程。

    我正在为你准备一个样品,但是我过度复杂了,将它包含在这里会有很多污染。我希望至少我让你朝着正确的方向前进。

答案 2 :(得分:1)

当你说“服务在15秒后终止”时,我认为你正在调试代码。

如果您没有任何选项且无法使用其他人建议的内容,则使用上面的代码,当您通过services.msc 安装和启动服务时,会正确触发计时器事件。但是,如果您正在调试服务,则不会触发计时器事件 ,并且应用程序将终止(如您所述)。我会创建一个在timer事件中调用的过程,并在ServiceExecute事件中调用一次,所以你可以这样调试:

procedure TSomeService.ServiceExecute(Sender: TService);
begin
  ExecuteSomeProcess(); // Put breakpoint here to debug
  while not self.Terminated do
    ServiceThread.ProcessRequests(true);
end;

procedure TSomeService.TimerTimer(Sender: TObject);
begin
  timer.Enabled := false;
  ExecuteSomeProcess(); // This can't throw any exception!
  timer.Enabled := true;
end;