我在项目中使用线程。我想立即杀死并终止一个线程。
样品:
type
test = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
var
Form1: TForm1;
a:tthread;
implementation
{$R *.dfm}
procedure test.Execute;
begin
Synchronize(procedure begin
form1.ProgressBar1.position := 0;
sleep(5000);
form1.ProgressBar1.position := 100;
end
);
end;
procedure TForm1.btn_startClick(Sender: TObject);
begin
a:=test.Create(false);
end;
procedure TForm1.btn_stopClick(Sender: TObject);
begin
terminatethread(a.ThreadID,1); //Force Terminate
end;
但是当我点击btn_stop
(点击btn_start
后)后,线程将不会停止。 那么如何立即停止此线程?
BTW a.terminate;
也不起作用。
感谢。
答案 0 :(得分:9)
这是对工作线程的完全滥用。您将所有线程的工作委托给主线程,使工作线程无用。您可以使用简单的计时器。
正确使用工作线程看起来更像是这样:
type
test = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
end;
var
Form1: TForm1;
a: test = nil;
implementation
{$R *.dfm}
procedure test.Execute;
var
I: integer
begin
Synchronize(
procedure begin
form1.ProgressBar1.Position := 0;
end
);
for I := 1 to 5 do
begin
if Terminated then Exit;
Sleep(1000);
if Terminated then Exit;
Synchronize(
procedure begin
Form1.ProgressBar1.Position := I * 20;
end
);
end;
Synchronize(
procedure begin
form1.ProgressBar1.Position := 100;
end
);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
btn_stopClick(nil);
end;
procedure TForm1.btn_startClick(Sender: TObject);
begin
if a = nil then
a := test.Create(False);
end;
procedure TForm1.btn_stopClick(Sender: TObject);
begin
if a = nil then Exit;
a.Terminate;
a.WaitFor;
FreeAndNil(a);
end;
答案 1 :(得分:1)
问题是线程使用Sleep等待。无论周围发生什么,此方法都会使线程在指定时间内保持休眠状态。为了能够“打破睡眠”你应该使用一个事件。代码应更改为:
procedure test.Execute;
begin
Synchronize(procedure begin
form1.ProgressBar1.position := 0;
end);
Event.WaitFor(5000);
if not IsTerminated then
Synchronize(procedure begin
form1.ProgressBar1.position := 100;
end);
end;
应该像这样创建和销毁事件:
constructor test.Create(aCreateSuspended: Boolean);
begin
inherited;
Event := TSimpleEvent.Create;
end;
destructor test.Destroy;
begin
FreeAndNil(Event);
inherited;
end;
为了停止线程,代码为:
procedure TForm1.btn_stopClick(Sender: TObject);
begin
a.Terminate;
end;
但是简单地调用Terminate不会发出事件信号,所以我们必须重新实现Terminate:
procedure test.Terminate;
begin
inherited;
Event.SetEvent;
end;
调用SetEvent将发出事件信号,因此它将唤醒线程。执行在下一行继续,它测试线程终止并决定是否执行代码的第二部分。