TThread Создание TButton, запатентованного TPanel - PullRequest
1 голос
/ 28 февраля 2011

У меня есть вопрос по поводу отдельного TThread создания MainThread TButton на MainThread TPanel. TPanel должен быть установлен как родительский элемент TButton.

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

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

не работает ...

ButtonVariableName находится в MainThread. TButton.Create() вызывается на отдельном TThread. ButtonVariableName.Parent также вызывается из Отдельного TThread.

FindComponent похоже, что ломается. Когда я удаляю это и помещаю кое-что еще там, это работает. Возможно, что FindComponent не работает при вызове из отдельного TThread, но я не уверен.

Есть указатели ^? LOL.

-i2programmer

Ответы [ 3 ]

4 голосов
/ 28 февраля 2011

Нельзя использовать VCL из вторичных потоков.Используйте Synchronize или Queue во вторичном потоке для выполнения кода, связанного с VCL, в контексте основного потока.

1 голос
/ 28 февраля 2011
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;
1 голос
/ 28 февраля 2011

Это должен был быть комментарий, но я хочу добавить код. Прежде всего, вы не должны вызывать 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;
...