How to implement thread which periodically checks something using minimal resources?

前端 未结 5 1631
长发绾君心
长发绾君心 2021-01-02 00:39

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 kn

相关标签:
5条回答
  • 2021-01-02 00:50

    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.

    0 讨论(0)
  • 2021-01-02 00:59

    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)?

    0 讨论(0)
  • 2021-01-02 01:02

    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.

    0 讨论(0)
  • 2021-01-02 01:02

    Use CreateWaitableTimer and SetWaitableTimer

    0 讨论(0)
  • 2021-01-02 01:03

    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.

    0 讨论(0)
提交回复
热议问题