Как безопасно добавить Таблицу в PageControl в событии TCond Onernect TIdCmdTCPServer?
Я хочу добавить Tabsheet
динамически к PageControl
когда клиент подключился к моему IdCmdTCPServer
такой же, как этот код:
procedure TForm1.IdCmdTCPServer1Connect(AContext: TIdContext);
var
ATabSheet: TTabSheet;
begin
ATabSheet := TTabSheet.Create(PageControl1);
ATabSheet.PageControl := PageControl1;
ATabSheet.Caption := 'Hello!';
{...}
end;
Это нормально, но при закрытии приложения я получаю EOSError с сообщением: "Системная ошибка. Код: 1400. Недопустимый дескриптор окна". Я был добавлен этот блок кода в TButton
"s OnClick
событие, и приложение закроется без каких-либо проблем. Есть ли более безопасный способ сделать это?
После помощи David Heffernan я изменил свой метод следующим образом:
....
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;
И результат теста команды:
но упомянутая проблема - сталь, происходящая при закрытии приложения!
2 ответа
Ваш обработчик событий и, следовательно, код доступа к VCL, который он содержит, выполняется в потоке, отличном от потока GUI. Весь код, который обращается к объектам VCL, должен выполняться в потоке GUI. Следовательно, вам нужно будет изменить свой код, чтобы убедиться, что части VCL перенаправляются в поток GUI.
Используйте TIdSync или TThread.Synchronize, чтобы маршалировать части VCL вашего кода в поток GUI. Реми приводит пример первого подхода здесь: Indy synchronize ServerTCPExecute
Окончательная правильная идея:
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