使用TThread.WaitFor时无法单击主窗体

时间:2016-08-04 13:22:30

标签: delphi

这是我的示例代码,我使用Waitfor等待线程完成

TCPThread = class(TThread)
protected
    procedure Execute; override;
public
    Source, Dest: String;
    FHandle:THandle;
    constructor Create(Source1, Dest1: string; TFHandle1: THandle);
end;

............

constructor TCPThread.Create(Source1, Dest1: string; TFHandle1: THandle);
begin
      inherited Create(False);
      Source:=Source1;
      Dest:=Dest1;
      FHandle:=TFHandle1;
end;

procedure TCPThread.Execute;
var
    Cancel : PBool;
begin
    Cancel := PBOOL(False);
    CopyFileEx(PChar(Source), PChar(Dest), @CopyFileProgress, Pointer(FHandle), Cancel, 0);
end;

进度条运行良好,但我无法点击任何按钮和任何地方,例如取消按钮。

我需要等待文件被复制,或者必要时可以取消它并清理

CPThread := TCPThread.Create('D:\test.iso', 'D:\test2.iso',FHandle);
CPThread.WaitFor;
CPThread.Destroy;

1 个答案:

答案 0 :(得分:7)

TThread.WaitFor()阻塞调用线程,直到线程终止。在主UI线程的上下文中调用时,WaitFor()不会处理挂起的窗口消息(但会处理挂起的TThread.Synchronize()TThread.Queue()请求)。这就是为什么你不能点击任何东西。

对于您尝试做的事情,请不要等待线程。让它在将控制权返回到主UI消息循环时正常运行,并让线程告诉您何时完成其工作。

此外,您滥用pbCancel的{​​{1}}参数。

尝试更像这样的事情:

CopyFileEx()

type
  TCPThread = class(TThread)
  private
    Cancel : BOOL;
    Source, Dest: String;
    FHandle: THandle;
  protected
    procedure Execute; override;
    procedure TerminatedSet; override;
  public
    constructor Create(Source1, Dest1: string; TFHandle1: THandle);
  end;

constructor TCPThread.Create(Source1, Dest1: string; TFHandle1: THandle);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  Source := Source1;
  Dest := Dest1;
  FHandle := TFHandle1;
end;

procedure TCPThread.Execute;
begin
  if not CopyFileEx(PChar(Source), PChar(Dest), @CopyFileProgress, Pointer(FHandle), @Cancel, 0) then
    ReturnValue := GetLastError;
end;

procedure TCPThread.TerminatedSet;
begin
  Cancel := True;
end;