如何在线程完成运行之前停止?

S.M*_*HDI 4 delphi multithreading

我有一个名为TMyThread的线程,我像这样覆盖Execute过程:

 procedure TMyThread.Execute;
 Begin
     repeat
     //Some Work 
     Sleep(5000);
     //Some Work 2;
     Sleep(5000); 
     until FActive=False
 End;
Run Code Online (Sandbox Code Playgroud)

在主窗体中,我有一个名为'Destroy My Thread'的按钮.我想破坏我的线程,但问题是我的线程只有在完成其工作时才会被销毁.我想破坏我的线程,即使它还没有完成它的工作.我该怎么做呢?

Dav*_*nan 22

您的线程的Execute方法必须定期检查线程Terminated属性的状态.如果是True,那么线程Execute方法必须退出.

因此,典型的Execute方法可能如下所示:

procedure TMyThread.Execute;
begin
  while not Terminated do
    DoNextPieceOfWork
end;
Run Code Online (Sandbox Code Playgroud)

看起来您的线程有自己的FActive标志执行相同的任务.问题在于TThread它不知道它.所以你应该摆脱FActive而不是使用内置机制.

当你打电话给Free它时,它会调用Terminate.那将TerminatedTrue.然后它等待线程方法退出.这不会发生,因为你的线程通知说TerminatedTrue和退出.然后线程的析构函数可以继续并完成整理线程的工作.


查看答案中的代码,可以更好地编写以利用现有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;
Run Code Online (Sandbox Code Playgroud)

现在不需要单独的Stop方法.你可以打电话Free给线程.然后Terminate被叫.然后TerminatedSet被称为.然后发出事件信号.然后Execute终止.然后线程可以消失.


话虽如此,我正在努力想到5000ms超时是最好的方法.我不知道你为什么要这样做,但我猜你正在试图限制线程,以免它变.你想避免繁忙的循环.这是令人钦佩的,但使用固定超时不是这样做的方法.这样做的方法是等待同步事件,通常是事件.然后,当还有更多工作要做时,事件就会发出信号并且您的线程会被唤醒.

  • 工作代码还需要检查终止. (2认同)

S.M*_*HDI 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;
Run Code Online (Sandbox Code Playgroud)

现在,如果我想终止我的线程,我所要做的就是调用 MyThread.Stop 而不是调用 MyThread.Free 。

  • 为什么选择实现自己的并行机制而不是使用 Terminate (3认同)
  • 要清楚如何执行此操作,您需要重写“TThread.TermminateSet”并调用“FTerminateEvent.SetEvent”。并确保在调用“inherited Destroy”后释放“FTerminateEvent”。请参阅我更新的答案。 (2认同)