TThread 创建以 TPanel 为父级的 TButton

发布于 2024-10-19 16:09:57 字数 751 浏览 5 评论 0原文

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

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

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

不起作用...

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

FindComponent 似乎是崩溃的原因。当我将其移除并在那里放置其他东西时,它就可以工作了。从单独的 TThread 调用时,FindComponent 可能不起作用,但我不确定。

有什么指点^? 哈哈。

-i2程序员

I have a question about Separate TThread creation of a MainThread TButton on a MainThread TPanel. The TPanel must be set as the TButton's Parent.

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

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

is not working...

ButtonVariableName is on MainThread.
TButton.Create() is being called on Separate TThread.
ButtonVariableName.Parent is also called from Separate TThread.

FindComponent seems to be what is breaking down. When I remove it and place something else there it works. It may be that FindComponent doesn't work when called from Separate TThread but I'm not certain.

Any pointers^?
LOL.

-i2programmer

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

巴黎盛开的樱花 2024-10-26 16:09:57

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

You can not use VCL from secondary threads. Use Synchronize or Queue in the secondary thread to execute VCL-related code in the context of the main thread.

愁以何悠 2024-10-26 16:09:57

这应该是一条评论,但我想包含一些代码。首先,您不应该从辅助线程调用任何 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;

This was supposed to be a comment but I want to include some code. First of all you're not supposed to call any VCL from secondary threads, so calling FindComponent is not guaranteed to work. Despite this fact, I doubt this is your problem, because unless you're especially lucky you will not get a race condition so you will not get an error.

You should do two things:

  • Put your code under a simple button on a form, test it, and when you know the code is good, move it to your background thread.
  • Brake up your code a bit so you can see what's failing where. No need to guess if FindComponent is the one that's failing when it's so easy to test and be sure.

Brake up your code like this:

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;
装纯掩盖桑 2024-10-26 16:09:57
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;
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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文