Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Динамичесоке создание компоненты в потоке - не получается [D7, XP]


Страницы:   1 2

kay ©   (2006-04-12 12:23:00) 

Есть компонента idTcpClient, которая при отсутствии соединения вешает программу.
Решил создать тред, который содержит эту компоненту, но не знаю какого Owner'а писать при создании. Если родителя сделать основную форму, то вылетает ошибка при записи в адрес 00000000

constructor TtcpThread.Create;
begin
 inherited Create(true);
 tcpClient.Create(ovpnRestarter);
 tcpClient.OnStatus:=tcpClientStatus;
end;


заголовок

type
 TtcpThread = class(TThread)
   private
     procedure tcpClientStatus(ASender: TObject; const AStatus: TIdStatus;
       const AStatusText: String);
   protected
     procedure Execute; override;
   public
     tcpClient: TIdTCPClient;
     constructor Create;
     destructor Destroy; override;
 end;


Сергей М.   (2006-04-12 14:01:00) [21]


> в конструкторе треда я его не создаю


Цитирую самый первый твой пост :


> constructor TtcpThread.Create;
> begin
>  inherited Create(true);
>   tcpClient.Create(ovpnRestarter);
>  tcpClient.OnStatus:=tcpClientStatus;
> end;


Выделенной жирным это что, спрашивается ?


Сергей М.   (2006-04-12 13:59:00) [22]


> sniknik ©   (12.04.06 13:53) [13]


Так он утечку схлопочет, ибо поток может быть приостановлен при выполнении блокирующего метода Connect(), после чего объект TtcpThread уничтожен .. При этом до finally (где выполняется разрушение TIdTCPClient) дело, разумеется, не доходит


kay   (2006-04-12 13:57:00) [23]

в конструкторе треда я его не создаю.
   public
     tcpClient: TIdTCPClient;
     destructor Destroy; override;


Сергей М.   (2006-04-12 13:56:00) [24]

Что-то я не понял ..

Объект TIdTCPClient ты создаешь дважды - первый раз в конструкторе треда, в второй в теле Execute ...


kay   (2006-04-12 13:55:00) [25]

ураЙ! получилось! вместо просто tcpClient.Free;

сделал
     tcpClient.Disconnect;
     tcpClient.Free;

ибо тред всё ещё работал и выполнялось убиение


sniknik   (2006-04-12 13:53:00) [26]

> tcpClient.OnStatus:= tcpClientStatus;
где и как описана? (проверь без нее)

потом если у тебя саздание в Execute то там и освождение делай... так примерно

procedure TtcpThread.Execute;
begin
 with TIdTCPClient.Create(nil) do
   try
      //OnStatus:=tcpClientStatus; для теста отключить

      Host:='www.google.com';
      Port:=80;
      Connect();
   finally
      Free;
   end;
end;


(тогда и constructor и destructor переопределять лишнее, пойдут стандартные, писать меньше, код короче, понятнее...)


kay   (2006-04-12 13:51:00) [27]

1) всё равно уж попробую тред добить. не получится - буду использовать TcpClient от борланда.

2)inherited

после нажатия F7 почемуто переходит на end метода TtcpThread.Execute;


Сергей М.   (2006-04-12 13:44:00) [28]


> для стандартного клиента нужно DNS lookup делать, что не
> хочется


В твоем случае любойкомпонент будет пытаться выполнять разрешение имени хоста в его IP-адрес - ты ведь указываешь хост не по адресу, а по имени ..


> баг возникает только если тред запустить


На какой конкретно строчке возникает исключение ?


kay   (2006-04-12 13:40:00) [29]

с Terminate такая же проблема =(


kay   (2006-04-12 13:38:00) [30]

может надо не Suspend, а Terminate?


kay   (2006-04-12 13:35:00) [31]

ну и на всякий случай
procedure TtcpThread.Execute;
begin
 tcpClient := TIdTCPClient.Create(nil);
 tcpClient.OnStatus:=tcpClientStatus;

 tcpClient.Host:='www.google.com';
 tcpClient.Port:=80;
 tcpClient.Connect();
end;


код запуска треда в самой программе:
tcp.Resume;
код остановки треда в программе:
tcp.Suspend;

после выхода из программы запускается деструктор и ошибка записи памяти 00000000


kay   (2006-04-12 13:33:00) [32]

destructor TtcpThread.Destroy;
begin

 if tcpClient <> nil then
   tcpClient.Free;

 inherited;
end;

забыл всё скопировать...

баг возникает только если тред запустить

антифриз не подходит. он всё равно приложение вешает, по крайней мере выходить из него не хочет.
а для стандартного клиента нужно DNS lookup делать, что не хочется.


Сергей М.   (2006-04-12 13:31:00) [33]


> вот код завершения треда:


Где этот код размещен ? В каком методе ?


kay   (2006-04-12 13:28:00) [34]

спасибо! а то я уже реализовал тред, но есть одно НО!

после того как запустить тред (Resume), выйти из него (Suspend) и завершить приложение, то возникает ошибка записи памяти 00000000.

вот код завершения треда:
 if tcpClient <> nil then
   tcpClient.Free;

 inherited;


kay   (2006-04-12 13:28:00) [35]

спасибо! а то я уже реализовал тред, но есть одно НО!

после того как запустить тред (Resume), выйти из него (Suspend) и завершить приложение, то возникает ошибка записи памяти 00000000.

вот код завершения треда:
 if tcpClient <> nil then
   tcpClient.Free;

 inherited;


Сергей М.   (2006-04-12 13:11:00) [36]


> kay ©   (12.04.06 12:52) [2]



> просто нужно проверять соединение с сервером


Поток здесь вовсе не обязателен.

Подойдет любой компонент, использующий асинхронный неблокирующий режим, например, TClientSocket.

TIdTCPClient же использует синхронный блокирующий режим, но и при его использовании необязательна организация дополнительного потока - достаточно бросить на форму компонент TIdAntifreeze.


kay   (2006-04-12 12:52:00) [37]

может есть компонента уже работающая в потоке. мнепросто нужно проверять соединение с сервером. в противном случае идёт процедура работы с соединением.


sniknik   (2006-04-12 12:33:00) [38]

> но не знаю какого Owner'а писать при создании.
nil пиши, и обязательно тогда уничтожай его в деструкторе

основная форма в потоке фигурировать никак не должна


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо