Правильный поток уничтожить

Привет. В моей форме я создаю TFrame во время выполнения. В этом кадре я создаю фоновый поток с выполнением команд в бесконечном цикле. Но когда я уничтожу этот фрейм, я должен разрушить эту нить. я попробую

thread.Suspend;
thread.Terminate;
FreeAndNil(thread);

но получить AV и ThreadError. Как мне уничтожить нить?


person Andrew Kalashnikov    schedule 24.09.2010    source источник
comment
возможный дубликат освободить TThread либо автоматически, либо вручную   -  person Craig Stuntz    schedule 24.09.2010
comment
Не приостанавливайте нить. Метод завершения просто устанавливает для свойства Terminated значение true, а ваш метод Execute отвечает за завершение потока. Если он приостановлен, у него не будет возможности прекратить действие.   -  person jachguate    schedule 25.09.2010
comment
Еще одна проблема с приведенным выше кодом заключается в том, что он, скорее всего, освобождает поток до того, как в него будет внесено изменение для нормального завершения.   -  person Andreas Rejbrand    schedule 25.09.2010


Ответы (3)


Вы должны убедиться, что поток выходит из своего метода Execute, чтобы завершить его правильно.

Код может быть примерно таким:

procedure TThread.Execute;
begin
  while not Self.Terminated do
  begin
    //do something
  end;
end;

Вызовите это, когда вы хотите уничтожить поток:

thread.Terminate;
thread.WaitFor;
FreeAndNil(thread);
person Linas    schedule 24.09.2010
comment
Нет необходимости вызывать Terminate и WaitFor извне, так как деструктор потока сделает это сам. Однако может потребоваться вызвать его из перезаписанных деструкторов, прежде чем какие-либо поля будут освобождены, чтобы убедиться, что они больше не используются в потоке. - person mghie; 25.09.2010

Достаточно сделать thread.Terminate. Но вы, вероятно, захотите установить thread.FreeOnTerminate := true при его создании.

Конечно, в тесном цикле вашего потока (то есть в Execute) вам нужно проверить, был ли поток запрошен на завершение (проверьте свойство Terminated). Если вы обнаружите, что поток был запрошен на завершение, просто прервите цикл и выйдите из Execute.

person Andreas Rejbrand    schedule 24.09.2010
comment
thread.Terminate только устанавливает для свойства FTerminated значение True. Он не разрушает нить. - person Linas; 24.09.2010
comment
Я знаю. Но каждый поток должен проверять это в своем методе Execute. Я предполагаю, что ОП делает это. - person Andreas Rejbrand; 24.09.2010

Вы никогда не должны вызывать приостановку в потоке, это небезопасно, и возобновление следует использовать только для запуска потока, который был создан приостановленным.

В Delphi 2010 функции приостановки и возобновления были упразднены, а метод start был введен для усиления этого.

Более полное объяснение см. в этой теме на форумах Codegears.

сказав, что есть 2 способа прекратить и освободить поток.

1: я устанавливаю FreeOnTerminate при создании потока, поэтому я просто звоню.

Thread.Terminate;

2: явно освободить поток, так как мне нужно прочитать результат из общедоступного свойства до освобождения потока и после его завершения.

Thread.Terminate;
Thread.WaitFor;
//Do somthing like read a public property from thread object
if Thread <> nil then FreeAndNil(Thread);

В основном цикле выполнения может быть хорошей идеей добавить некоторую обработку исключений. Или вам может быть интересно, почему поток завершает сам себя. Это может быть причиной AV, если для потока установлено значение FreeOnTerminate, и он уже был освобожден, когда вы пытаетесь его освободить.

procedure TThread.Execute;
begin
  while not Terminated do
  begin
    try
      //do something
    except
      on E:Exception do
       //handle the exception
    end;
  end;
end; 
person Mike Taylor    schedule 26.09.2010