0

我想在另一个线程中运行的 OmniThreadLibrary 工作任务中实现重复性任务。例如,该任务应每 3 秒执行一次。因此,我写了一个TOmniWorker带有实例的后代,TTimer如下所示:

program Project14;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  Vcl.ExtCtrls,
  Vcl.Forms,
  OtlTaskControl;

type
  TMyTimerWorker = class(TOmniWorker)
  strict private
    FTimer: TTimer;
    procedure DoOnTimer(Sender: TObject);
  protected
    function Initialize: Boolean; override;
    procedure Cleanup; override;
  end;

{ TMyTimerWorker }

procedure TMyTimerWorker.Cleanup;
begin
  FTimer.Free;
  inherited;
end;

procedure TMyTimerWorker.DoOnTimer(Sender: TObject);
begin
  Beep;
end;

function TMyTimerWorker.Initialize: Boolean;
begin
  Result := inherited;
  if not Result then exit;

  FTimer := TTimer.Create(nil);
  FTimer.OnTimer  := DoOnTimer;
  FTimer.Interval := 3000;
  FTimer.Enabled  := True; // note: this isn't necessary, but is added to avoid hints that 'Enabled' might be 'False'
end;

var
  LTimerWorker: IOmniWorker;
begin
  try
    LTimerWorker := TMyTimerWorker.Create;
    CreateTask(LTimerWorker).Unobserved.Run;
    while True do
      Application.ProcessMessages;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Initialize我在和中设置断点DoOnTimer。前者执行得很好,但后者根本不会被调用。顺便说一句:Cleanup两者都没有被调用,所以任务仍在运行。

我究竟做错了什么?TTimer在 OTL 任务中使用 a 是不可能的吗?如果是,为什么?

更新:我找到了() 的解决方法TTimer但为什么TTimer方法不起作用?

4

1 回答 1

3

基于YouTTimer的代码不起作用,因为TTimer默认情况下使用 windows 消息来触发计时器事件并且 windows 消息不会在 OTL worker 中处理。

调用.MsgWait之前.Run和内部工作循环将使用MsgWaitForMultipleObjects而不是WaitForMultipleObjects允许消息处理。

话虽如此,您真的不应该TTimer在后台任务中使用,因为 - 正如其他人所说 -TTimer不是线程安全的。

于 2015-07-08T15:55:03.040 回答