Как реализовать поток, который периодически проверяет что-то, используя минимальные ресурсы?
Я хотел бы иметь поток, выполняющийся в фоновом режиме, который будет проверять соединение с некоторым сервером с заданным интервалом времени. Например, каждые 5 секунд.
Я не знаю, есть ли для этого хороший "шаблон"? Если я правильно запомню, я кое-что прочитал, что спящий поток в его методе выполнения не очень хорош. Но я могу ошибаться.
Кроме того, я мог бы использовать обычную библиотеку потоков TThread или OTL.
Любые идеи?
Спасибо.
Ответы
Ответ 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.
Ответ 5
Используйте CreateWaitableTimer и SetWaitableTimer