1.Terminate и Free the thread, когда пользователь нажимает кнопку остановки и создает новую, когда они нажимают кнопку запуска.
Это, безусловно, вариант, если накладные расходы минимальны.
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 не позволяют приостанавливать/возобновлять потоки, потому что весь дизайн (и концепция) был испорчен. Вам следует избегать попыток сделать это и переключиться на использование сигнальных событий (например, TEvent). См. Различные типы событий в SyncObjs. –
смотри также http://stackoverflow.com/questions/4401171/self-suspending-a-thread-in-delphi-when-its-not-needed-and-safely-resuming – kludg