我有一个问题,即在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
答案 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;