Подтвердить что ты не робот

Как реализовать поток, который периодически проверяет что-то, используя минимальные ресурсы?

Я хотел бы иметь поток, выполняющийся в фоновом режиме, который будет проверять соединение с некоторым сервером с заданным интервалом времени. Например, каждые 5 секунд.

Я не знаю, есть ли для этого хороший "шаблон"? Если я правильно запомню, я кое-что прочитал, что спящий поток в его методе выполнения не очень хорош. Но я могу ошибаться.

Кроме того, я мог бы использовать обычную библиотеку потоков TThread или OTL.

Любые идеи?

Спасибо.

4b9b3361

Ответ 1

Вы можете использовать событие и реализовать метод Execute потомка TThread с помощью цикла с WaitForSingleObject, ожидающего события, с указанием тайм-аута. Таким образом, вы можете разбудить поток сразу, когда это необходимо, например. при завершении.

Ответ 2

В 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;

Что касается сна в Execute - это зависит от того, как вы это делаете. Если вы используете "Сон", это может быть не очень мудрым (например, потому что это предотвратит остановку потока во время сна). Сон с 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 хранятся в списке приоритетов (в основном таймеры сортируются по времени "следующего появления" ), а внутренний диспетчер MsgWaitForMultipleObjects в TOmniWorker задает соответствующее значение таймаута для таймера с наивысшим приоритетом.

Ответ 3

Если поток работает в течение всего срока действия приложения, его можно просто закрыть операционной системой на приложении и не нужно точное время, зачем беспокоиться о решениях, требующих большего набора текста, чем sleep (5000)?

Ответ 4

Чтобы добавить еще одно средство для достижения 5-секундного события, можно использовать Мультимедийный таймер, аналогичный TTimer, но не зависящий от вашего приложения. После его настройки (вы можете настроить однократное или повторяющееся), он вызывает вас в другом потоке. По своей природе он очень точен (с точностью до 1 мс). См. пример кода Delphi здесь.

Код для вызова таймера прост и поддерживается на всех платформах Windows.