Ошибка дескриптора Delphi TThread - PullRequest
0 голосов
/ 30 июня 2018

Я читаю «Высокая производительность Delphi», и мне чего-то не хватает. Учитывая этот код в качестве теста:

type TTest = class(TThread)
  private
    amemo: TMemo;
  public
    constructor Create(ss: boolean; memo: TMemo);
  protected
    procedure Execute; override;
end;

constructor TTest.Create(ss: boolean; memo: TMemo);
begin
  inherited Create(ss);
  FreeOnTerminate := true;
  amemo := memo;
end;

procedure TTest.Execute;
var i: uint32;
begin
  inherited;
  i := 0;

  while not Terminated do
    begin
      Inc(i);
      Synchronize(procedure
                  begin amemo.Lines.Add(i.ToString) end);
      Sleep(1000);
    end;

end;

Очень просто, эта тема печатает некоторые цифры в заметке. Я запускаю поток приостановлено, и поэтому я должен вызвать этот кусок кода:

procedure TForm1.Button1Click(Sender: TObject);
begin
  thread := TTest.Create(true, Memo1);
  thread.Start;
end;

Я всегда останавливал поток, вызывающий thread.Terminate;, но, читая книгу, я вижу, что Primoz останавливает поток, как это:

procedure TForm1.Button2Click(Sender: TObject);
begin
  thread.Terminate;
  thread.WaitFor; //he adds this method call
  //FreeAndNil(thread)
  //there is the above line as well in the code copied from the book but I have removed it since I have set FreeOnTerminate := true (so I dont have to worry about freeing the obj).
end;

На этом этапе, если я запускаю код, используя только Terminate, у меня нет проблем. Если я запускаю код с Terminate + WaitFor, я получаю эту ошибку:

enter image description here

Я читал больше кодирования и в delphi, и вижу, что Ник Ходжес просто звонит на Terminate;. Достаточно ли вызова Terminate;, чтобы безопасно остановить поток? Обратите внимание, что я установил FreeOnTerminate := true, поэтому я не забочусь о смерти объекта. Прекращено должно остановить выполнение (то, что внутри выполнения), и это должно быть так:

  • Вызов прерван
  • Выполнить остановки
  • Поток останавливает выполнение
  • Тема теперь свободна (FreeOnTerminate: = true)

Пожалуйста, скажите мне, что мне не хватает.


Примечание. В книге нет темы FreeOnTerminate := true. Таким образом, поток должен быть освобожден вручную; Я думаю, что это причина, почему он звонит

thread.Terminate;
thread.WaitFor;
FreeAndNil(thread)

Я согласен с Terminate (остановить поток = и FreeAndNil (освободить объект вручную), но WaitFor?

1 Ответ

0 голосов
/ 01 июля 2018

Пожалуйста, скажите мне, что мне не хватает.

В документации для FreeOnTerminate прямо сказано, что вы не можете использовать поток в любым способом после Terminate.

Включает ваш WaitFor вызов, который будет работать на возможно уже свободном объекте. Это использование после освобождения может вызвать вышеуказанную ошибку, в том числе и более «интересные» варианты поведения.

...