“暂停"具有属性的线程 [英] "Pausing" A Thread With A Property

查看:100
本文介绍了“暂停"具有属性的线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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:

  1. 当用户单击停止"时终止并释放该线程,并在单击开始"时创建一个新线程.
  2. 使用sleep来延迟线程(我不想这样做)
  3. 具有一个布尔值属性,用于确定线程是否已暂停.仅当此布尔值为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆