问题
I would like to have a thread running in background which will check connection to some server with given time interval. For example for every 5 seconds.
I don't know if there is a good "desing pattern" for this? If I remember corretly, I've read somewehere that sleeping thread in its execute method is not good. But I might be wrong.
Also, I could use normal TThread class or OTL threading library.
Any ideas?
Thanks.
回答1:
You could use an event and implement the Execute
method of the TThread
descendant by a loop with WaitForSingleObject
waiting for the event, specifying the timeout. That way you can wake the thread up immediately when needed, e.g. when terminating.
回答2:
In OmniThreadLibrary, you would do:
uses
OtlTask,
OtlTaskControl;
type
TTimedTask = class(TOmniWorker)
public
procedure Timer1;
end;
var
FTask: IOmniTaskControl;
procedure StartTaskClick;
begin
FTask := CreateTask(TTimedTask.Create())
.SetTimer(1, 5*1000, @TTimedTask.Timer1)
.Run;
end;
procedure StopTaskClick;
begin
FTask.Terminate;
FTask := nil;
end;
procedure TTimedTask.Timer1;
begin
// this is triggered every 5 seconds
end;
As for sleeping in Execute - it depends on how you do it. If you use Sleep, then this might not be very wise (for example because it would prevent the thread to stop during the sleep). Sleeping with WaitForSingleObject is fine.
An example of TThread and WaitForSingleObject:
type
TTimedThread = class(TThread)
public
procedure Execute; override;
end;
var
FStopThread: THandle;
FThread: TTimedThread;
procedure StartTaskClick(Sender: TObject);
begin
FStopThread := CreateEvent(nil, false, false, nil);
FThread := TTimedThread.Create;
end;
procedure StopTaskClick(Sender: TObject);
begin
SetEvent(FStopThread);
FThread.Terminate;
FThread.Free;
CloseHandle(FStopThread);
end;
{ TTimedThread }
procedure TTimedThread.Execute;
begin
while WaitForSingleObject(Form71.FStopThread, 5*1000) = WAIT_TIMEOUT do begin
// this is triggered every 5 seconds
end;
end;
OTL timer implementation is similar to the TThread code above. OTL timers are kept in priority list (basically the timers are sorted on the "next occurence" time) and internal MsgWaitForMultipleObjects dispatcher in TOmniWorker specifies the appropriate timeout value for the highest-priority timer.
回答3:
If the thread runs for the life of the app, can be simply terminated by the OS on app close and does not need accurate timing, why bother with solutions that require more typing than sleep(5000)?
回答4:
To add another means of achieving a 5-sec event it is possible to use the Multimedia Timer which is similar to TTimer but has no dependence on your application. After configuring it (you can setup one-shot or repetitive) it calls you back in another thread. By its nature it is very accurate (to within better than 1ms). See some sample Delphi code here.
The code to call the timer is simple and it is supported on all Windows platforms.
回答5:
Use CreateWaitableTimer and SetWaitableTimer
来源:https://stackoverflow.com/questions/8412254/how-to-implement-thread-which-periodically-checks-something-using-minimal-resour