Reputation: 11
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
Upvotes: 1
Views: 320
Reputation: 139
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;
Upvotes: 1
Reputation: 25678
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:
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;
Upvotes: 1
Reputation: 26830
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.
Upvotes: 4