2011-02-28 4 views
1

MainThread TPanelTThread MainThread의 생성 TButton에 대한 질문이 있습니다. TPanelTButton의 학부모로 설정해야합니다. TThread TButton의 생성 TPanel에 의해 양육 됨

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

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

ButtonVariableName

이 MainThread에 ... 작동하지 않습니다. TButton.Create()이 Separate TThread에서 호출되고 있습니다. ButtonVariableName.Parent도 분리형 TThread에서 호출됩니다.

FindComponent 무엇이 고장 났는가? 내가 그것을 제거하고 거기에 다른 것을 놓으면 작동합니다. 개별 전화 TThread에서 전화 할 때 FindComponent이 작동하지 않을 수도 있지만 확실하지 않습니다.

모든 포인터 ^? LOL.

-i2 프로그래머

+4

윈도우가 생성되는 스레드와 친 화성이있다. 실제로 이것은 여러 스레드로 UI를 구현하는 것을 실질적으로 불가능하게 만듭니다. 또한 무의미합니다. UI를 주 스레드에 넣고 스레드에서 장시간 실행되는 비 시각적 작업을 실행하십시오. –

+1

포기 - UI 컨트롤과 함께 스레드를 사용하려고해도 전혀 문제가 없습니다. – Misha

답변

4

보조 스레드에서 VCL을 사용할 수 없습니다. 주 스레드의 컨텍스트에서 VCL 관련 코드를 실행하려면 보조 스레드에서 동기화 또는 대기열을 사용하십시오.

+0

이것은 내가 전화하는 방법입니다. Synchronize(); 'procedure TMyThread.forButton; begin 버튼 [ItemCounter] : = TButton.Create ((Form1.FindComponent (tsl [0 + 3])을 TComponent로 사용)); 동기화 (@forButton);하지만 여전히 작동하지 않습니다. – i2programmer

+4

@ i2programmer : StackOverflow에서 질문을 편집 할 수 있습니다. 귀하의 질문에 귀하의 의견을 코드를 포함하고 적절하게 형식을 지정하는 것이 더 도움이 될 것입니다 ({} 버튼을 사용하거나 단순히 4 개의 공백으로 들여 쓰기). –

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
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; 
+0

+1은 OP가 원하는 것을 수행하는 코드입니다. 그러나 문제는 여전히 남아 있습니다. 왜? IMO는 주어진 조언을 따르고 스레드에서이를 피하십시오. –

+2

-1 이것은 의미가 없습니다. 주 스레드로 다시 직렬화 할 수 있도록 스레드를 만듭니다. 왜?! –

+0

아마도 TMyThread.Execute가 버튼을 만드는 것 이외의 다른 일을하기 때문에 ... OP가 얻으려고하는 것은 스레드 내부에서 발생하는 상황에 따라 UI를 업데이트하는 것입니다. (아마 취소 버튼을 추가하십시오. 스레드가 X 초 이상 실행 된 후 ...). 이 작업을 수행하는 올바른 방법은 주 스레드에 콜백을 추가하고 버튼 생성을 처리하도록하는 것입니다. 그러나 그것은 단지 추측입니다. –

관련 문제