由TPanel创建的TButton创建

时间:2011-02-28 09:12:14

标签: multithreading delphi button panel lazarus

我有一个问题,即在MainThread TThread上单独TButton创建MainThread TPanel。必须将TPanel设置为TButton的父级。

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

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

无效...

MainThread上有

ButtonVariableName。 正在调用TButton.Create()来分离TThread。 ButtonVariableName.Parent也来自单独的TThread

FindComponent似乎正在崩溃。当我删除它并在那里放置其他东西时,它会起作用。从FindComponent调用时,TThread可能无效,但我不确定。

任何指针^? LOL。

-i2programmer

3 个答案:

答案 0 :(得分:4)

您无法从辅助线程使用VCL。在辅助线程中使用Synchronize或Queue在主线程的上下文中执行与VCL相关的代码。

答案 1 :(得分: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; 是否失败。

像这样制作你的代码:

{{1}}

答案 2 :(得分: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;