无法终止线程

时间:2013-08-14 15:45:26

标签: multithreading delphi delphi-xe4

我在项目中使用线程。我想立即杀死并终止一个线程。

样品:

    type
      test = class(TThread)
      private
        { Private declarations }
      protected
        procedure Execute; override;
      end;

    var
     Form1: TForm1;
     a:tthread;

    implementation

    {$R *.dfm}

    procedure test.Execute;
    begin

      Synchronize(procedure begin    
          form1.ProgressBar1.position := 0;
          sleep(5000);
          form1.ProgressBar1.position := 100;    
      end
      );

    end;

   procedure TForm1.btn_startClick(Sender: TObject);
   begin
     a:=test.Create(false);
   end;

   procedure TForm1.btn_stopClick(Sender: TObject);
   begin
     terminatethread(a.ThreadID,1);  //Force Terminate
   end;

但是当我点击btn_stop(点击btn_start后)后,线程将不会停止。 那么如何立即停止此线程?

BTW a.terminate;也不起作用。

感谢。

2 个答案:

答案 0 :(得分:9)

这是对工作线程的完全滥用。您将所有线程的工作委托给主线程,使工作线程无用。您可以使用简单的计时器。

正确使用工作线程看起来更像是这样:

type
  test = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;
  a: test = nil;

implementation

{$R *.dfm}

procedure test.Execute;
var
  I: integer
begin
  Synchronize(
    procedure begin    
      form1.ProgressBar1.Position := 0;
    end
  );

  for I := 1 to 5 do
  begin
    if Terminated then Exit;
    Sleep(1000);
    if Terminated then Exit;
    Synchronize(
      procedure begin
        Form1.ProgressBar1.Position := I * 20;
      end
    );
  end;

  Synchronize(
    procedure begin
      form1.ProgressBar1.Position := 100;    
    end
  );
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  btn_stopClick(nil);
end;

procedure TForm1.btn_startClick(Sender: TObject);
begin
  if a = nil then
    a := test.Create(False);
end;

procedure TForm1.btn_stopClick(Sender: TObject);
begin
  if a = nil then Exit;
  a.Terminate;
  a.WaitFor;
  FreeAndNil(a);
end;

答案 1 :(得分:1)

问题是线程使用Sleep等待。无论周围发生什么,此方法都会使线程在指定时间内保持休眠状态。为了能够“打破睡眠”你应该使用一个事件。代码应更改为:

procedure test.Execute;
begin
  Synchronize(procedure begin    
      form1.ProgressBar1.position := 0;
  end);
  Event.WaitFor(5000);
  if not IsTerminated then
    Synchronize(procedure begin    
        form1.ProgressBar1.position := 100;    
    end);
end;

应该像这样创建和销毁事件:

constructor test.Create(aCreateSuspended: Boolean);
begin
  inherited;
  Event := TSimpleEvent.Create;
end;

destructor test.Destroy;
begin
  FreeAndNil(Event);
  inherited;
end;

为了停止线程,代码为:

procedure TForm1.btn_stopClick(Sender: TObject);
begin
  a.Terminate;
end;

但是简单地调用Terminate不会发出事件信号,所以我们必须重新实现Terminate:

procedure test.Terminate;
begin
  inherited;
  Event.SetEvent;
end;

调用SetEvent将发出事件信号,因此它将唤醒线程。执行在下一行继续,它测试线程终止并决定是否执行代码的第二部分。