我想在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
也没有被调用,所以任务仍在运行。
我做错了什么?是否无法在OTL任务中使用TTimer
?如果是,为什么?
更新:我找到了TTimer
({}的workaround,但为什么TTimer
接近不起作用?
答案 0 :(得分:3)
You TTimer
-based code doesn't work because TTimer
uses windows messages to trigger the timer event and windows messages are not processed in an OTL worker by default.
Call .MsgWait
before .Run
and internal worker loop will use MsgWaitForMultipleObjects
instead of WaitForMultipleObjects
which will allow for message processing.
Saying that, you really should not use TTimer
in background tasks because - as others have said - TTimer
is not threadsafe.