如何让delphi应用程序(正在运行)在特定时间/日期执行某些操作

时间:2010-01-10 15:58:09

标签: delphi

我的应用程序在未使用时位于系统托盘中。

用户可以将事件配置为按特定计划发生。例如,他们可能会在下午5点或每个星期三下午3点或每个月的16日上午10点执行任务。

假设我的delphi程序一直在运行,它会在启动时启动,这是delphi支持触发这些预定事件的最佳方式。

显然,TTimer可用于根据已用时间安排事件,但它们似乎不适合此问题。

干杯

6 个答案:

答案 0 :(得分:17)

您可以使用我的CRON合规Cromis Scheduler。它甚至支持一些cron没有的东西。例如,基于时间间隔的事件和从/到时间帧。我在很多软件中使用它并证明它本身非常有用。它是免费的,非常轻巧,适用于线程并经过生产测试。如果您需要任何进一步的帮助,请发邮件给我。

其他方式是:

  1. 使用已建议的Windows调度API。但这可能会在OS-es之间发生变化。
  2. 使用具有调度程序单元的JCL(JVCL中的组件),但我发现很难直接使用代码。这就是我写自己的原因。

答案 1 :(得分:8)

我会使用Microsoft Task Scheduler API:

http://msdn.microsoft.com/en-us/library/aa383614(VS.85).aspx

如果您不想做“肮脏的工作”,可以使用Delphi Wrappers,但我不知道是否有免费的。您可以查看

如果您不想使用Microsoft Scheduler,可以使用CronJob组件:http://www.appcontrols.com/components.html。它也是共享软件,但很容易实现(只是一个onAlert事件)。

答案 2 :(得分:1)

您需要一个计划组件。有many available,但我似乎无法找到任何免费的。您可以根据TTimer自行构建一个,或尝试访问Task Scheduling API.

然而,让计时器每分钟执行一项任务以检查任务是否到期,太多更简单。

答案 3 :(得分:1)

您可以在程序中实现某种进程间通信,并通过ipc通过Windows调度服务调用的程序触发这些事件。这种方法的优点是您不需要编写用户界面来设置计划,而且ipc可能在其他方面证明是有用的。

答案 4 :(得分:0)

由于您的应用程序正在运行,您可以使用idle事件查看是否已经过预设日期/时间,如果已经过,则执行您的计时。这种方法的唯一副作用是,如果应用程序繁忙,您的事件将不会触发,但是定时器(用于处理消息队列的TTimer需要处理,或者应用程序需要“空闲”)也不会触发除非你使用线程计时器)。

uses
  ...,DateUtils; // contains IncMinute

type
  TForm1 = Class(TForm)
    :
    procedure FormCreate(Sender: TObject);
  private 
    fTargetDate : tDateTime;
    procedure AppIdle(Sender: TObject; var Done: Boolean);
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  fTargetDate := 0.0;
  Application.OnIdle := AppIdle;
  fTargetDate := IncMinute(Now,2);
end;

procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean);
begin
  if (fTargetDate <> 0.0) and (Now >= fTargetDate) then
    begin
      fTargetDate := 0.0;
      ShowMessage('started');
    end;
 end;

编辑如果您有多次需要运行某些内容,请按日期/时间放置在有序列表中,然后仅跟踪将运行的NEXT时间。当某些内容运行时,它将被删除以供列表使用(或重新安排回列表并重新排序列表)。

答案 5 :(得分:0)

另一种选择是创建一个执行计时器管理的TThread:

type
  TestThreadMsg = class(tThread)
  private
    fTargetDate : tDateTime;
    fMsg : Cardinal;
  protected
    procedure Execute; override;
    procedure NotifyApp;
  public
    constructor Create( TargetDate : TDateTime; Msg:Cardinal);
  end;

实现:

constructor TestThreadMsg.Create(TargetDate: TDateTime; Msg: Cardinal);
begin
  inherited Create(True);
  FreeOnTerminate := true;
  fTargetDate := TargetDate;
  fMsg := Msg;
  Suspended := false;
end;

procedure TestThreadMsg.Execute;
begin
  Repeat
    if Terminated then exit;
    if Now >= fTargetDate then
      begin
        Synchronize(NotifyApp);
        exit;
      end;
    Sleep(1000); // sleep for 1 second, resoultion = seconds
  Until false;
end;

procedure TestThreadMsg.NotifyApp;
begin
  SendMessage(Application.MainForm.Handle,fMsg,0,0);
end;

然后可以将其连接到主要表单:

const
  WM_TestTime = WM_USER + 1;

TForm1 = Class(TForm)
  :
  procedure FormCreate(Sender: TObject);
  procedure WMTestTime(var Msg:tMessage); message WM_TestTime;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  TestThreadMsg.Create(IncSecond(Now,5),WM_TestTime);
end;

procedure TForm1.WMTestTime(var Msg: tMessage);
begin
  ShowMessage('Event from Thread');
end;