Delphi:从框架中引用线程控制

时间:2011-08-04 19:24:46

标签: delphi pointers tframe refer

有一个 FRAME (不是表单)和一个帖子。如何从线程中引用Frame的控件?例如,我想从线程中禁用一个按钮。但我没有指向按钮的指针,框架中没有全局变量。

谢谢!

2 个答案:

答案 0 :(得分:7)

你实际上不应该调用任何方法或修改VCL控件的任何属性,或者用户可见的任何东西(应用程序的用户界面,这意味着VCL通常在Delphi中控制,无论是在框架中还是不)直接来自后台线程。

然而,您可以使用PostMessageTThread.SynchronizeTThread.Queue向主要帖子发送活动或通知。

不是在线程对象中引用框架或控件,而是将包含框架或其他控件的窗体的句柄传递给线程,并使用用户消息( WM_USER + 10001),如this.

我更喜欢PostMessage到TTHread.Synchronize或Queue,因为它非常简单并且效果很好。它不是一个跨平台友好的技术,因为它与Win32 API绑定。

您应该像这样调用同步:

  TMyThread = class(TThread)
  private
    FFrame: TFrame;
    ...
  public
    constructor Create(AFrame: TFrame); 
    ...
  end;

  constructor TMyThread.Create(AFrame: TFrame);
  begin
    FFrame := AFrame;
    inherited Create;
  end;

  // do not call directly, only using Synchronize
  procedure TMyThread.AMethodWithNoParameters; 
  begin
     FFrame.Button1.Enabled := not FBusy;
  end;

  procedure TMyThread.DoWork; // called from Execute.
  begin
    FBusy := true; 
    Synchronize(AMethodWithNoParameters);
    Sleep(100); //dummy;
    FBusy := false; 
    Synchronize(AMethodWithNoParameters);
  end;

答案 1 :(得分:2)

正确地指出,你不能在后台线程中调用任何可视组件的任何成员。

要从线程代码内部禁用按钮,您必须具有对按钮的引用或对可以分配线程对象的事件的引用 - 然后您可以在排队或同步过程内触发线程,如此: -

    type
      test=class(tthread)
         ondisablebutton:tnotifyevent;

{...}

然后,在使用tthread.synchronize封装的过程中,您可以调用该事件,而不是忘记测试它是否已分配....

procedure test.synchronisedprocedure;
begin
  if assigned(ondisablebutton) then
    ondisablebuttone(self);
end;

当你创建你设计的线程对象时,你必须将ondisablebutton分配给包含按钮的表单的过程,如下所示: -

procedure form1.threadwantstodisablebutton(sender:tobject);
begin
  button1.enabled:=false;
end;

你的线程创建需要额外的一行: -

  mythread:=test.create;
  test.ondisablebutton:=form1.threadwantstodisablebutton;

就像这样,显然你必须能够访问form1(或包含按钮的表单),你可以在其中定义和创建你的线程,这不一定是好的设计,但它可以工作。