"Приостановка" потока со свойством
У меня есть объект TThread и я хочу иметь возможность запускать / останавливать поток с помощью кнопки на главной форме программы. Я искал способы сделать это, и до сих пор у меня есть следующие идеи:
- Завершите и освободите поток, когда пользователь нажмет кнопку "Стоп", и создайте новый, когда он нажмет "Пуск".
- Используйте сон, чтобы задержать поток (я не хочу этого делать)
- Имейте свойство, которое является логическим, чтобы определить, приостановлен ли поток или нет. Код в Execute произойдет только в том случае, если это логическое значение false.
Я склоняюсь к #3. Будет ли установка логического свойства для объекта TThread из главной формы поточно-ориентированным?
Какой из этих вариантов или лучшую альтернативу я должен выбрать? Я впервые использую темы, поэтому любая помощь приветствуется.
2 ответа
1.Откройте и освободите поток, когда пользователь нажимает "Стоп", и создайте новый, когда он нажмет "Пуск".
Это, безусловно, вариант, если накладные расходы минимальны.
3. Иметь свойство, которое является логическим, чтобы определить, приостановлен поток или нет. Код в Execute произойдет только в том случае, если это логическое значение false.
Вы можете сделать это, но вам придется регулярно проверять это логическое значение, и, если оно установлено, вводить цикл ожидания, пока он не будет очищен или пока не будет сообщено, что поток завершен.
Будет ли установка логического свойства для объекта TThread из главной формы поточно-ориентированным?
Это так же потокобезопасно, как вызов TThread.Terminate()
, который просто устанавливает логическое значение TThread.Terminated
имущество.
Какой из этих вариантов или лучшую альтернативу я должен выбрать?
Я использую вариант № 4 - использование сигнальных событий вместо логических. Например:
type
TMyThread = class(TThread)
private
FRunEvent, FTermEvent: TEvent;
FWaitEvents: THandleObjectArray;
procedure CheckPause;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create; reintroduce;
destructor Destroy; override;
procedure Pause;
procedure Unpause;
end;
constructor TMyThread.Create;
begin
inherited Create(False);
FRunEvent := TEvent.Create(nil, True, True, '');
FTermEvent := TEvent.Create(nil, True, False, '');
SetLength(FWaitEvents, 2);
FWaitEvents[0] := FRunEvent;
FWaitEvents[1] := FTermEvent;
end;
destructor TMyThread.Destroy;
begin
FRunEvent.Free;
FTermEvent.Free;
inherited;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
// do some work...
CheckPause;
// do some more work...
CheckPause;
// do some more work...
CheckPause;
//...
end;
end;
procedure TMyThread.TerminatedSet;
begin
FTermEvent.SetEvent;
end;
procedure TMyThread.CheckPause;
var
SignaledEvent: THandleObject;
begin
while not Terminated do
begin
case TEvent.WaitForMultiple(FWaitEvents, INFINITE, False, SignaledEvent) of
wrSignaled: begin
if SignaledEvent = FRunEvent then Exit;
Break;
end;
wrIOCompletion: begin
// retry
end;
wrError: begin
RaiseLastOSError;
end;
end;
SysUtils.Abort;
end;
procedure TMyThread.Pause;
begin
FRunEvent.ResetEvent;
end;
procedure TMyThread.Unpause;
begin
FRunEvent.SetEvent;
end;
Посмотрите вики для Delphi о запуске и остановке потоков здесь: http://docwiki.embarcadero.com/RADStudio/Berlin/en/Starting_and_Stopping_Threads
Это применимо еще к Delphi 7. Это может быть применимо и дальше, но я не могу подтвердить более ранние версии.