2014-08-27 86 views
0

这是我的要求:
需要应用程序或任务,它以可配置的时间间隔(在Delphi中)以全天候运行。调度服务需要的建议

我到目前为止所做的:
所以我决定去Windows服务。 然后我在Delphi中创建了windows服务。

过程是
1.创建的Windows服务启动():

procedure TDemo.ServiceStart(Sender: TService; var Started: Boolean); 
begin 
    MyServiceThread := TMyThread.Create(False); //Call the thread 
    MyServiceThread.Resume; 
end; 

2. Windows服务站();

procedure TDemo.ServiceStop(Sender: TService; var Stopped: Boolean); 
begin 
    MyServiceThread.Terminate; 
end; 
  1. 线程的Execute方法:

    procedure TMyThread.Execute; begin MyTask(); end;

MyTask()有一些功能和它可能需要30秒到5分钟的时间完成任务。

如果现在我开始服务,那么它调用execute方法并调用MyTask()。然后我完成任务。它只会发生一次。因为根本没有循环。

然后我创建了任务调度程序和设置的10 分钟的时间间隔,并调用其启动我的Windows服务和 停止该批处理文件。

现在一切工作正常。每10分钟我的任务就完成了。

什么是所有其他的可能性,而不是任务计划?服务本身可以做吗?哪一个是最好的方法?

思考,发现一个解决方案:
1.Creating定时器线程内。但是Timer需要将时间设置为Configurable one.It可能是一天或一周等等。

什么是Timer支持的最大时间?

定时器可以吗?

是否有其他方法可以做到这一点?

请给我一些建议去寻求更好的解决方案。

+1

为什么不使用系统的调度程序?为什么重新发明轮子? – 2014-08-27 08:06:08

回答

0

首先,我不知道你的Delphi版本,但一般TThread.Resume已被弃用。您应该使用TThread.Start。但即便如此,您也不需要启动线程,因为它是使用False参数创建的 - 即不是暂停状态。

Execute()只执行一次,因为您这样做了。

下面的代码是一个简单的线程,在一段时间间隔内“执行”。

TMyThread = class(TThread) 
    private  
     fRefreshInterval: Integer; // milliseconds 
     fTerminateEvent: TEvent; 

     procedure SetRI(const Value: Integer); 
    protected 
     procedure Execute; override;  
    public 
     constructor Create(const aRefreshInterval: Integer = 600000); 
     destructor Destroy; override; 
     property RefreshInterval: Integer write SetRI; 
    end; 

//// implementation 

constructor TMyThread.Create; 
begin 
    inherited Create(False); 
    fRefreshInterval := aRefreshInterval; 
    fTerminateEvent := TEvent.Create(nil, True, False, ''); 
    Priority := tpLowest; 
    FreeOnTerminate := True; 
end; 

destructor TMyThread.Destroy; 
begin 
    try 
    if not Terminated then 
    begin 
     Terminate; 
     fTerminateEvent.SetEvent;  
    end; 

    fTerminateEvent.Free; 
    except 
    // 
    end; 
    inherited; 
end; 

procedure TMyThread.Execute; 
begin 
    while not Terminated do 
    begin 
    try 

     // your code here 

    except 
     // something bad happened 
    end; 

    fTerminateEvent.WaitFor(fRefreshInterval); 
    end; 
end; 

procedure TMyThread.SetRI(const Value: Integer); 
begin 
    InterlockedExchange(fRefreshInterval, Value); 
end; 

如果要执行你的任务每XX分钟,你要记住你的任务执行所需的时间和应该做的事情,如:

procedure TMyThread.Execute; 
var 
    taskStartedAt: Cardinal; 
    taskDuration: Cardinal; 
begin 
    while not Terminated do 
    begin 
    taskStartedAt := GetTickCount; 
    try 

     // your code here 

    except 
     // something bad happened 
    end; 

    taskDuration := GetTickCount - taskStartedAt; 

    if (fRefreshInterval > taskDuration) then 
     fTerminateEvent.WaitFor(fRefreshInterval - taskDuration); 
    end; 
end; 

反正TTimerTask Scheduler也是选择。

+0

感谢彼得的快速回复。定时器间隔是否可配置?我可以使用ini文件来配置计时器的时间间隔吗? – 2014-08-27 08:55:43

+0

只要您喜欢,您可以通过其“属性RefreshInterval”配置时间间隔。另外,您可以通过构造函数的输入参数初始化它。 – 2014-08-27 09:02:41

0

在Windows服务中有一个计时器是一种选择。你也可以在开始新的实例之前检查你的前一个实例是否已经完成。但是,如果您必须不时地控制服务,这可能不是正确的选择。

多年来,我发现Autosys是最有用的调度代理。它带有客户端 - 服务器模型。所以你可以控制你的Autosys客户端工具的工作。

TechScheduler是另一种选择,但现在它非常老派。

1

您可以使用创建计时器的方法。

现在,如果您可以基于系统时钟安排任务(例如从下午3点开始),那么您可以使用下一个方法。而不是改变定时器的时间间隔,以便在特定的时间触发,让您的定时器保持在1分钟的时间间隔。然后,每当定时器启动时,只需检查系统时间是否大于预定时间。如果是你需要做什么处理,那么你什么也不做。

所以现在你只需要一个有序的列表来存储排序顺序中的所有计划任务,这样你就不需要遍历整个列表并检查每个任务个体是否需要执行。

现在,如果使用系统closk不是一个选项,因为用户可以更改它实现自己的计数器,每当计时器触发时它都会增加。所以现在你只需要调整你的计时逻辑到你的计数器系统。

编辑:我建议的方法是在每个任务需要一定时间的时间骑乘多人游戏浏览器游戏中共同使用。所以服务器只在某个事件发生时根据某个任务的命令执行时间而存储,并且该任务需要多少时间才能完成。

0

我宁愿去用“预定任务”方法。这就是 这样一个任务的Windows原生方法,您只需要在计划任务中定义的每个时间间隔创建一个名为 的控制台应用程序。