“暂停"具有属性的线程 [英] "Pausing" A Thread With A Property
问题描述
我有一个TThread对象,并且希望能够通过程序主窗体上的按钮来启动/停止线程.我一直在研究实现此目的的方法,到目前为止,我有以下想法:
I have a TThread object and want to be able to start/stop the thread via a button on the main form of the program. I've been looking into ways to do this and so far I have the following ideas:
- 当用户单击停止"时终止并释放该线程,并在单击开始"时创建一个新线程.
- 使用sleep来延迟线程(我不想这样做)
- 具有一个布尔值属性,用于确定线程是否已暂停.仅当此布尔值为false时,才会执行Execute中的代码.
我倾向于#3.从主窗体在TThread对象上设置布尔属性是否是线程安全的?
I'm leaning towards #3. Would setting a boolean property on the TThread object from the main form be threadsafe?
我应该选择这些选项中的哪个或其他更好的选择?这是我第一次使用线程,因此很感谢您的帮助.
Which of these options, or any better alternative, should I go with? This is my first time using threads so any help is appreciated.
推荐答案
1.在用户单击停止"时终止并释放该线程,并在其单击开始"时创建一个新线程.
1.Terminate and Free the thread when the user clicks stop and create a new one when they click start.
如果开销很小,这当然是一个选择.
This is certainly an option, if the overhead is minimal.
3.具有一个布尔值属性,用于确定线程是否已暂停.仅当此布尔值为false时,才会执行Execute中的代码.
3.Have a property that is a boolean to determine if the thread is paused or not. The code in the Execute will only happen if this boolean is false.
您可以这样做,但是您必须定期检查布尔值,如果设置了布尔值,则进入一个等待循环,直到清除它或发出终止信号的信号为止.
You could do that, but you would have to check that boolean regularly and if set then enter a wait loop until either it is cleared or the thread is signaled to terminate.
从主窗体中的TThread对象设置布尔属性是否是线程安全的?
Would setting a boolean property on the TThread object from the main form be threadsafe?
与调用TThread.Terminate()
一样,它是线程安全的,它只需设置boolean TThread.Terminated
属性即可.
It is as thread-safe as calling TThread.Terminate()
, which simply sets the boolean TThread.Terminated
property.
我应该选择其中哪些选项,或者其他更好的选择?
Which of these options, or any better alternative, should I go with?
我使用选项#4-使用信号事件而不是布尔值.例如:
I use option #4 - using signaled events instead of booleans. For example:
type
TMyThread = class(TThread)
private
FRunEvent, FTermEvent: TEvent;
FWaitEvents: THandleObjectArray;
procedure CheckPause;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create; reintroduce;
destructor Destroy; override;
procedure Pause;
procedure Unpause;
end;
constructor TMyThread.Create;
begin
inherited Create(False);
FRunEvent := TEvent.Create(nil, True, True, '');
FTermEvent := TEvent.Create(nil, True, False, '');
SetLength(FWaitEvents, 2);
FWaitEvents[0] := FRunEvent;
FWaitEvents[1] := FTermEvent;
end;
destructor TMyThread.Destroy;
begin
FRunEvent.Free;
FTermEvent.Free;
inherited;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
// do some work...
CheckPause;
// do some more work...
CheckPause;
// do some more work...
CheckPause;
//...
end;
end;
procedure TMyThread.TerminatedSet;
begin
FTermEvent.SetEvent;
end;
procedure TMyThread.CheckPause;
var
SignaledEvent: THandleObject;
begin
while not Terminated do
begin
case TEvent.WaitForMultiple(FWaitEvents, INFINITE, False, SignaledEvent) of
wrSignaled: begin
if SignaledEvent = FRunEvent then Exit;
Break;
end;
wrIOCompletion: begin
// retry
end;
wrError: begin
RaiseLastOSError;
end;
end;
SysUtils.Abort;
end;
procedure TMyThread.Pause;
begin
FRunEvent.ResetEvent;
end;
procedure TMyThread.Unpause;
begin
FRunEvent.SetEvent;
end;
这篇关于“暂停"具有属性的线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!