![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамичесоке создание компоненты в потоке - не получается [D7, XP]
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 пиши, и обязательно тогда уничтожай его в деструкторе
основная форма в потоке фигурировать никак не должна