我有一个名为TMyThread的线程,我像这样覆盖执行程序:
procedure TMyThread.Execute;
Begin
repeat
//Some Work
Sleep(5000);
//Some Work 2;
Sleep(5000);
until FActive=False
End;
在主窗体中,我有一个名为'Destroy My Thread'的按钮。我想破坏我的线程,但问题是我的线程只有在完成其工作时才会被销毁。我想破坏我的线程,即使它还没有完成它的工作。我该怎么做?
答案 0 :(得分:22)
您的线程的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
终止。然后线程可以消失。
话虽如此,我很难想象5000ms超时是最好的方法。我不知道你为什么要这样做,但我猜你正在试图限制线程,以便它不会运行 hot 。你想避免繁忙的循环。这是令人钦佩的,但使用固定超时不是这样做的方法。这样做的方法是等待同步事件,通常是事件。然后,当还有更多工作要做时,事件就会发出信号并且你的线程会被唤醒。
答案 1 :(得分:2)
使用TEvent可以解决这个问题 这是一个例如:
uses SyncObjs;
TMyThread = class(TThread)
private
FTerminateEvent: TEvent;
protected
procedure Execute; override ;
public
constructor Create(ACreateSuspended: Boolean); overload;
destructor Destroy; override;
procedure Stop;
end;
constructor TMyThread.Create(ACreateSuspended: Boolean);
begin
FTerminateEvent := TEvent.Create(nil, True, False, 'FTerminateEvent');
inherited Create(ACreateSuspended);
end;
destructor TMyThread.Destroy;
begin
FTerminateEvent.Free;
inherited;
end;
procedure TMyThread.Stop;
begin
Terminate;
FTerminateEvent.SetEvent;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
// do somthing interesting!
FTerminateEvent.WaitFor(5000);
end;
end;
现在如果我要杀死我的线程,我所要做的就是调用MyThread.Stop而不是调用MyThread.Free。
答案 2 :(得分:1)
你真的正在接近这个问题。将您的线程编码为只做您希望他们做的工作,然后就不需要“从外部进入”来控制它们。你觉得有必要从外面控制这个线程,因为它正在做你不想要它做的事情 - 那么你为什么要编写它来做到这一点?