2013-05-30 6 views
0

Я хочу добавить Tabsheet динамически в PageControl, когда клиент подключается к моей IdCmdTCPServer же, как этот код:Как безопасно добавить таблицу в файл PageControl в событии OnConnect TIdCmdTCPServer?

procedure TForm1.IdCmdTCPServer1Connect(AContext: TIdContext); 
var 
    ATabSheet: TTabSheet; 
begin 
    ATabSheet := TTabSheet.Create(PageControl1); 
    ATabSheet.PageControl := PageControl1; 
    ATabSheet.Caption := 'Hello!'; 
    {...} 
end; 

его хорошо, но при закрытии приложения я буду получать EOSError с сообщением:. «Системная ошибка код : 1400. Недопустимый дескриптор окна ". Я добавил этот код в событие TButtonOnClick, и приложение закроется без каких-либо проблем. Есть ли более безопасный способ сделать это?


После David Heffernan «s помощи, я изменил свой Methode так:

.... 

type 
    TMyThrd = class(TThread) 
    protected 
     procedure Execute; override; 
    end; 

... 

procedure TMyThrd.Execute; 
begin 
    with TTabsheet.Create(Form1.PageControl1) do 
    PageControl := Form1.PageControl1; 
end; 

... 

procedure TForm1.cmdAddTabCommand(ASender: TIdCommand); 
begin 
    with TMyThrd.Create(True) do 
    begin 
    FreeOnTerminate := True; 
    Resume; 
    end; 
end; 

И тест команды Результат:

addtab Command Testing Result

но указанная проблема является сталь происходит по заявке закрыть!

+0

может быть, это будет способствовать http://stackoverflow.com/q/9139940/1699210 – bummi

+0

@bummi: спасибо за ваше предложение. но я проверил свои части кода TCP, и они отлично работают без этого блочного кода в событии OnConnect. просто когда я добавлю этот блок, проблема появится! –

ответ

1

Ваш обработчик событий и, следовательно, код доступа VCL, который он содержит, выполняется в потоке, отличном от потока графического интерфейса. Весь код, который обращается к объектам VCL, должен выполняться в потоке графического интерфейса пользователя. Следовательно, вам нужно будет изменить свой код, чтобы убедиться, что части VCL настроены на поток графического интерфейса.

Используйте TIdSync или TThread.Synchronize, чтобы маршалировать части VCL вашего кода на поток GUI. Remy дает пример первого подхода здесь: Indy synchronize ServerTCPExecute

+0

Спасибо. проверьте этот вопрос еще раз. Я внес некоторые изменения в код, но ... –

+0

Вы должны делать то, что я говорю в ответ. Вызовите TThread.Synchronize. Не создавайте еще один поток! –

+0

какая тема? 'TThread', который вы говорите, является классом, именно я должен синхронизировать базу идентификаторов этого класса? –

0

Final правильная идея:

uses 
..., IdSync, ... 
... 

type 
    TSyncThrd = class(TIdSync) 
    protected 
    procedure DoSynchronize; override; 
end; 

... 

procedure TForm1.cmdAddTabCommand(ASender: TIdCommand); 
begin 
    with TSyncThrd.Create do 
    begin 
    try 
     Synchronize; 
    finally 
     Free; 
    end; 
    end; 
end; 

... 


procedure TSyncThrd.DoSynchronize; 
begin 
    with TTabsheet.Create(Form1.PageControl1) do 
    PageControl := Form1.PageControl1; 
end; 

Конечно текущее соединение должно быть закрыто до применения закрытия. Если нет, произойдет invalid pointer operation!

Специально благодаря David Heffernan