TThread的中断睡眠方法(仅睡眠方式)

时间:2018-03-16 12:00:19

标签: multithreading delphi

我正在寻找快速中断TThread的能力。

有人建议用TerminateThread打断它,但我不想要这种暴力行为。

我在Execute方法中实施了退出检查,但有一件事我无法影响:正在进行Sleep。当一个帖子在Sleep时,我唯一要做的就是等到Sleep完成。

我做了以下解决方法:

procedure TMyThreadTimer._smartSleep(Timeout: Integer);
var
  repeats: Integer;
begin
  repeats := (Timeout div 50) + 1;
  while (not Terminated) and (repeats > 0) do begin
    Sleep(50);
    Dec(repeats);
  end;
end;

但看起来不太好。

是否有能力中断Sleep,但不能中断线程?

1 个答案:

答案 0 :(得分:7)

使用TEvent对象代替Sleep(),例如:

type
  TMyThreadTimer = class(TThread)
  private
    FTermEvent: TEvent;
    procedure _smartSleep(Timeout: Integer);
  protected
    procedure Execute; override;
    procedure TerminatedSet; override; // XE2+ only *
  public
    constructor Create(ACreateSuspended: Boolean); override;
    destructor Destroy; override;
  end;

constructor TMyThreadTimer.Create(ACreateSuspended: Boolean);
begin
  inherited Create(ACreateSuspended);
  FTermEvent := TEvent.Create(nil, True, False, '');
end;

destructor TMyThreadTimer.Destroy;
begin
  //inherited calls TerminatedSet where FTermEvent should not be freed yet
  inherited;
  FTermEvent.Free;
end;

procedure TMyThreadTimer.Execute;
begin
  ...
end;

procedure TMyThreadTimer.TerminatedSet;
begin
  FTermEvent.SetEvent;
end;

procedure TMyThreadTimer._smartSleep(Timeout: Integer);
begin
  FTermEvent.WaitFor(Timeout);
end;

这样,当线程正常运行时,_smartSleep()将更有效地睡眠,并且只要您Terminate()线程(Terminate()调用TerminatedSet()),任何正在进行的睡眠都会立即停止。

* 如果您使用的是XE2之前的Delphi版本,则必须实施自己的方法,以便在需要时发出TEvent信号。例如,向线程类添加公共Stop()方法并让其调用Terminate()FTermEvent.SetEvent(),然后调用该方法,而不是直接调用Terminate()