对于 Windows 服务,我需要一个计时器来定期执行特定任务。当然,有许多选项似乎优于计时器(多线程,直接从服务的主线程调用方法),但在这种特定情况下它们都有其缺点。
然而,由于显而易见的原因,如果没有 GUI 的消息队列,SetTimer() 就无法工作。我所做的(在 Free Pascal 中)如下:
创建计时器:
MyTimerID := SetTimer(0, 0, 3333, @MyTimerProc);
在服务的主循环中,运行计时器队列:
procedure TMyServiceThread.Execute;
var
AMessage: TMsg;
begin
repeat
// Some calls
if PeekMessage(AMessage, -1, WM_TIMER, WM_TIMER, PM_REMOVE) then begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;
// Some more calls
TerminateEventObject.WaitFor(1000);
until Terminated;
end;
最后,终止计时器:
KillTimer(0, MyTimerID)
除了 KillTimer 总是返回 False 之外,这按预期工作。
但是,我对您的反馈感兴趣,如果我的实现是正确的 - 我只是想避免弄乱其他应用程序的消息和其他我不知道的副作用,因为我对消息处理缺乏经验。
Thanks!
我会选择一个可等待定时器。不需要消息队列。
function WaitableTimerDelayFromMilliseconds(milliseconds: Integer): TLargeInteger;
begin
Result := 0 - (TLargeInteger(milliseconds) * 10000);
end;
procedure TMyServiceThread.Execute;
var
TimerInterval: Integer;
DueTime: TLargeInteger;
hTimer: THandle;
Handles: array[0..1] of THandle;
begin
TimerInterval := 10000; // use whatever interval you need
DueTime := WaitableTimerDelayFromMilliseconds(TimerInterval);
hTimer := CreateWaitableTimer(nil, FALSE, nil);
if hTimer = 0 then RaiseLastOSError;
try
if not SetWaitableTimer(hTimer, DueTime, TimerInterval, nil, nil, False) then RaiseLastOSError;
try
Handles[0] := TerminateEventObject.Handle;
Handles[1] := hTimer;
while not Terminated do
begin
case WaitForMultipleObjects(2, PWOHandleArray(@Handles), False, INFINITE) of
WAIT_FAILED:
RaiseLastOSError;
WAIT_OBJECT_0+0:
Terminate;
WAIT_OBJECT_0+1:
begin
// do your work
end;
end;
end;
finally
CancelWaitableTimer(hTimer);
end;
finally
CloseHandle(hTimer);
end;
end;
Update:或者,正如 David Heffernan 所建议的,您可以自行等待终止事件:
procedure TMyServiceThread.Execute;
var
TimerInterval: Integer;
begin
TimerInterval := 10000; // use whatever interval you need
while not Terminated do
begin
case TerminateEventObject.WaitFor(TimerInterval) of
wrSignaled:
Terminate;
wrTimeout:
begin
// do your work
end;
wrError:
RaiseLastOSError;
end;
end;
end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)