1

我有一个关于在 MainThread上单独TThread创建 MainThread的问题。必须设置为的父级。 TButtonTPanelTPanelTButton

ButtonVariableName := TButton.Create (
    (Form1.FindComponent('PanelNameString') as TComponent)
   );

ButtonVariableName.Parent := (
    (Form1.FindComponent('PanelNameString') as TWinControl)
  );

不管用...

ButtonVariableName在主线程上。 TButton.Create()正在单独的 TThread 上调用。 ButtonVariableName.Parent也从分离中调用TThread

FindComponent似乎是什么正在崩溃。当我删除它并在那里放置其他东西时它可以工作。从“单独”调用时可能FindComponent不起作用,TThread但我不确定。

任何指针^?哈哈。

-i2程序员

4

3 回答 3

4

您不能从辅助线程使用 VCL。在辅助线程中使用 Synchronize 或 Queue 可以在主线程的上下文中执行 VCL 相关的代码。

于 2011-02-28T09:30:38.383 回答
1

这应该是一个评论,但我想包含一些代码。首先,您不应该从辅助线程调用任何 VCL,因此FindComponent不能保证调用有效。尽管如此,我怀疑这是你的问题,因为除非你特别幸运,否则你不会得到竞争条件,所以你不会得到错误。

你应该做两件事:

  • 将您的代码放在表单上的一个简单按钮下,对其进行测试,当您知道代码是好的时,将其移至您的后台线程。
  • 稍微停止你的代码,这样你就可以看到哪里出了问题。当它很容易测试和确定时,无需猜测是否FindComponent是失败的。

像这样分解你的代码:

var ParentPanel: TWinControl;
    anControl: TControl;
begin
  Assert(Assigned(Form1)); // Assertions are free, you might as well test everything
  anControl := Form1.FindComponent('YourNameHere'); // casting straight to TWinControl raises an error if the returned control is nil
  Assert(Assigned(anControl)); // Make sure we got something
  ParentPanel := anControl as TWinControl; // raises error if the control is not TWinControl
  ButtonVariableName := TButton.Create(ParentPanel);
  ButtonVariableName.Parent := ParentPanel;
end;
于 2011-02-28T10:07:05.343 回答
1
type
  TMyThread = class( TThread )
  private
    FOwner : TComponent;
    procedure DoCreateButton;
  public
    constructor Create(AOwner: TComponent);
    procedure Execute; override;
  end;

.....

{ TMyThread }

constructor TMyThread.Create(AOwner: TComponent);
begin
  inherited Create(True);
  FreeOnTerminate := True;

  FOwner := AOwner;
  Resume;
end;

procedure TMyThread.DoCreateButton;
begin
  with TButton.Create(FOwner) do
  begin
    //Set the button Position 
    Left := 5;
    Top := 5;

    Parent := FOwner as TWinControl;
  end;
end;

procedure TMyThread.Execute;
begin
  Synchronize(DoCreateButton);
end;


{ Form1 }

procedure TForm1.btnExecClick(Sender: TObject);
begin
  TMyThread.Create(Panel1);
end;
于 2011-02-28T11:40:45.857 回答