スレッドのExecuteメソッドは、スレッドのTerminatedプロパティの状態を定期的にチェックする必要があります。の場合はTrue、スレッドExecuteメソッドを終了する必要があります。
したがって、一般的なExecute方法は次のようになります。
procedure TMyThread.Execute;
begin
while not Terminated do
DoNextPieceOfWork
end;
スレッドにはFActive、同じタスクを実行している独自のフラグがあるようです。それに関する問題はそれTThreadについて知らないということです。FActiveしたがって、組み込みのメカニズムを取り除き、代わりに使用する必要があります。
Freeスレッドを呼び出すと、が呼び出されますTerminate。それはに設定TerminatedされますTrue。次に、スレッドメソッドが終了するのを待ちます。これは、スレッドがそれを認識して終了するために発生しTerminatedますTrue。そして、スレッドのデストラクタは、スレッドを整理する作業を続行して終了できます。
Terminateあなたの答えのコードを見ると、既存のメカニズムを利用するように書かれたほうがよいでしょう。
type
TMyThread = class(TThread)
private
FTerminateEvent: TEvent;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create(ACreateSuspended: Boolean);
destructor Destroy; override;
end;
constructor TMyThread.Create(ACreateSuspended: Boolean);
begin
inherited Create(ACreateSuspended);
FTerminateEvent := TEvent.Create(nil, True, False, '');
end;
destructor TMyThread.Destroy;
begin
inherited;
FTerminateEvent.Free;
end;
procedure TMyThread.TerminatedSet;
begin
FTerminateEvent.SetEvent;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
// do somthing interesting!
FTerminateEvent.WaitFor(5000);
end;
end;
Stopこれで、別のメソッドは必要ありません。Freeスレッドを呼び出すだけです。その後Terminate、と呼ばれます。そして、TerminatedSetと呼ばれます。次に、イベントが通知されます。その後、Execute終了します。そして、スレッドが消えることができます。
そうは言っても、5000ミリ秒のタイムアウトが最善のアプローチであるシナリオを考えるのに苦労しています。なぜこれをしているのかわかりませんが、スレッドが熱くならないようにスロットルを調整しようとしていると思います。ビジーループを避けたい。それは素晴らしいことですが、固定タイムアウトを使用することはそれを行う方法ではありません。これを行う方法は、同期イベント(通常はイベント)を待機することです。その後、実行する作業が増えると、イベントが通知され、スレッドがウェイクアップします。