我需要独立于Form Thread工作。 例如,我的Thread有一个无限循环:

procedure TCustomThread.doProc;
begin
  repeat
.
.
.
  until (1 = 2);
end;

procedure TCustomThread.Execute;
begin
  inherited;

  Synchronize(doProc);
end;
.
.
.
procedure TForm1.Button1Click(Sender: TObject);
var
  thrd : TCustomThread;
begin
  thrd := TCustomThread.Create(True);
  thrd.Resume;
  Application.ProcessMessages;
end;

现在,当我单击Button1 ,我的Thread运行但主Form已锁定。 我怎样才能避免暂停Form

===============>>#1 票数:9 已采纳

ProcessMessages的调用是错误的,应该删除。 作为一个广泛而通用的规则,应该避免调用ProcessMessages 而这个根本没有任何意义。

其余代码只运行一个非终止循环。 它使用Synchronize来确保非终止循环在主线程上运行。 因此主线程无法为其消息循环提供服务。

线程的整个目的是能够执行单独的执行线程。 通过使用Synchronize您将在主线程中运行所有代码。 您的代码相当于将非终止循环放在主线程中。

您想要在不同的线程中执行代码。 所以你应该避免调用Synchronize 这应该仅用于必须在主线程上执行的小型,快速的工作。 通常是GUI更新。

你的execute方法应该是:

procedure TCustomThread.Execute;
begin
  while not Terminated do
  begin
    ....
  end;
end;

这引入了你的循环,但循环现在在线程中执行。 您现在可以在循环体内添加线程的有用代码。

请记住,任何使用VCL组件都必须在主线程上进行。 这就是使用Synchronize的地方。

===============>>#2 票数:0

TThread.Synchronize()在主线程的上下文中运行指定的过程,而不是在工作线程的上下文中。 所以你的循环在主线程中运行,并且不让主线程处理来自其消息队列的新消息。 这就是您的UI在线程运行时没有响应的原因。

你需要将你的线程重组为更像这样的东西:

procedure TCustomThread.doUpdateUI;
begin
  ... do something that updates the UI here ...
end;

procedure TCustomThread.Execute;
begin
  while not Terminated do
  begin
    ... do something in the worker thread ...
    Synchronize(doUpdateUI);
    ... do something else in the worker thread ...
  end;
end;

var
  thrd : TCustomThread = nil;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if thrd = nil then
    thrd := TCustomThread.Create(False);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if thrd <> nil then
  begin
    thrd.Terminate;
    thrd.WaitFor;
    FreeAndNil(thrd);
  end;
end;

  ask by Mohammadreza translate from so

未解决问题?本站智能推荐: