«Приостановка» потока со свойством

У меня есть объект TThread и я хочу иметь возможность запускать / останавливать поток с помощью кнопки в основной форме программы. Я искал способы сделать это, и до сих пор у меня есть следующие идеи:

Завершите и освободите поток, когда пользователь нажмет кнопку «Стоп», и создайте новый, когда он нажмет кнопку «Пуск».Используйте сон, чтобы задержать поток (я не хочу этого делать)Имейте свойство, которое является логическим, чтобы определить, приостановлен ли поток или нет. Код в Execute произойдет только в том случае, если это логическое значение false.

Я склоняюсь к # 3. Будет ли установка логического свойства для объекта TThread из главной формы поточно-ориентированным?

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

 kludg22 июл. 2016 г., 04:40
смотрите такжеstackoverflow.com/questions/4401171/...
 Ken White22 июл. 2016 г., 02:12
Последние версии Delphi не позволяют приостанавливать / возобновлять потоки, потому что весь дизайн (и концепция) были ошибочными. Вам следует избегать попыток сделать это и переключиться на использование сигнальных событий (например, TEvent). Смотрите различные типы событий в SyncObjs.

Ответы на вопрос(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;
 Nasreddine Galfout21 нояб. 2017 г., 14:59
Реми, что такоеSysUtils.Abort; вCheckPause метод, используемый для.
 Remy Lebeau21 нояб. 2017 г., 18:47
Это поднимаетEAbort исключение для немедленного завершения потока (так какExecute() не улавливает) в следующий разCheckPause() называется послеTerminate() был вызван.

http://docwiki.embarcadero.com/RADStudio/Berlin/en/Starting_and_Stopping_Threads

Это применимо еще к Delphi 7. Это может быть применимо и дальше, но я не могу подтвердить более ранние версии.

 Rob Kennedy22 июл. 2016 г., 05:42
Добро пожаловать в стек переполнения. Ты не ответил на вопрос. Вопрос требует рекомендации, но вы не предоставили ее. пожалуйстаредактировать Ваш ответ так, чтобы он отвечал на то, что задает вопрос.
 Ken White22 июл. 2016 г., 03:42
Это комментарий к вопросу, а не ответ. Ответы содержат соответствующую информацию здесь, в самом посте, со ссылками, используемыми только для предоставления дополнительной ссылки. Ответы должны стоять сами по себе, чтобы они содержали значение, если удаленное местоположение по какой-либо причине недоступно (перемещено, отключено или что-то еще). Ссылка только ответы не делай так.

Ваш ответ на вопрос