场景: 用户随机按开始按钮几次,然后必须停止所有产生的线程(单击TerminateButton)。
问题: 如何正确终止/等待/释放用户执行的所有线程?
通常,如果我必须运行指定数量的线程,我只会使用线程数组,然后对数组中的所有项目循环.terminate / .waitfor / free。 但是在这种情况下,我无法执行此操作,因为未确定线程数。
procedure TForm1.StartButtonClick(Sender: TObject);
begin
WorkerThread:=TWorkerThread.Create(true);
WorkerThread.FreeOnTerminate:=false;
WorkerThread.Resume;
end;
procedure TWorkerThread.Execute;
begin
repeat
//some code here
until Terminated=true;
end;
procedure TForm1.TerminateButtonClick(Sender: TObject);
begin
if Assigned(WorkerThread)=true then // <-This will work only for last instance
begin
WorkerThread.terminate; // <-This will work only for last instance
WorkerThread.waitfor; // <-This will work only for last instance
FreeAndNil(WorkerThread); // <-This will work only for last instance
end;
end;
答案 0 :(得分:0)
此刻,我将所有线程存储在TList中。此示例代码似乎可以正常工作。
procedure TForm1.FormCreate(Sender: TObject);
begin
InitializeCriticalSection(CriticalSection);
ThreadList:=TList.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteCriticalSection(CriticalSection);
end;
procedure TForm1.StartButtonClick(Sender: TObject);
begin
EnterCriticalSection(CriticalSection); //<- This will be required in my real multithreaded code
WorkerThread:=TWorkerThread.Create(true);
ThreadList.Add(WorkerThread);
WorkerThread.FreeOnTerminate:=false;
WorkerThread.OnTerminate:=form1.ThreadTerminated;
WorkerThread.Resume;
LeaveCriticalSection(CriticalSection);
end;
procedure TWorkerThread.Execute;
begin
repeat
sleep(random(1000));
until Terminated=true;
end;
procedure TForm1.ThreadTerminated(Sender: TObject);
begin
form1.Memo1.Lines.Add('terminated');
end;
procedure TForm1.TerminateButtonClick(Sender: TObject);
var x:integer;
begin
form1.Memo1.Clear;
EnterCriticalSection(CriticalSection); //<- This will be required in my real multithreaded code
for x:=0 to ThreadList.Count-1 do
begin
if Assigned(ThreadList.Items[x])=true then
begin
WorkerThread:=ThreadList.Items[x];
WorkerThread.Terminate;
WorkerThread.waitfor;
FreeAndNil(WorkerThread);
end;
end;
ThreadList.Clear;
LeaveCriticalSection(CriticalSection);
end;