如何实现使用最少资源定期检查某些内容的线程?

时间:2011-12-07 08:22:03

标签: multithreading delphi delphi-2009 tthread omnithreadlibrary

我想在后台运行一个线程,它会在给定的时间间隔内检查与某个服务器的连接。例如,每5秒钟。

我不知道这是否有一个好的“设计模式”?如果我记得正确的话,我已经读过一些在其执行方法中睡眠线程不好的地方。但我可能错了。

另外,我可以使用普通的TThread类或OTL线程库。

有什么想法吗?

感谢。

5 个答案:

答案 0 :(得分:16)

OmniThreadLibrary中,你会这样做:

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;

至于在执行中睡觉 - 这取决于你如何做。如果你使用Sleep,那么这可能不是很明智(例如因为它会阻止线程在休眠期间停止)。和WaitForSingleObject一起睡觉很好。

TThread和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计时器实现类似于上面的TThread代码。 OTL定时器保存在优先级列表中(基本上定时器按“下一次出现”时间排序),TOmniWorker中的内部MsgWaitForMultipleObjects调度程序为最高优先级定时器指定适当的超时值。

答案 1 :(得分:14)

您可以使用事件并通过Execute等待事件的循环实现TThread后代的WaitForSingleObject方法,指定超时。这样,您可以在需要时立即唤醒线程,例如终止时。

答案 2 :(得分:1)

如果线程在应用程序的生命周期中运行,可以通过应用程序关闭的操作系统终止,并且不需要准确的计时,为什么还需要更多打字而不是睡眠(5000)?

答案 3 :(得分:1)

要添加另一种实现5秒事件的方法,可以使用类似于TTimer的多媒体计时器,但不依赖于您的应用程序。配置后(您可以设置一次性或重复性),它会在另一个线程中回拨您。就其性质而言,它非常准确(在1ms以内)。查看一些sample Delphi code here

调用计时器的代码很简单,所有Windows平台都支持它。

答案 4 :(得分:0)