![]() |
| ||
|
|
Новости |
Поиск |
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 17:16:00) [1]
> как убить тред в любой момент времени, чтобы от него ничего
> не осталось?
>
Собственно тред как ОС-объект "убивается" явным или неявным вызовом TerminateThread().
sniknik (2006-04-12 17:11:00) [2]> как убить тред в любой момент времени, чтобы от него ничего не осталось?
в моем примере у тебя на это времени не будет... вторую кнопку нажать не успееш он уже "убьется" и следа не останется.
sniknik (2006-04-12 17:09:00) [3]> я так понял при выходе их приложения вызывается метод Terminate?
нет. Terminate нужен (сдесь, в TThread) чтобы прервать и завершить Execute (у тебя этого не используется, нормально на это проверки в цикле ставить... но у тебя и цикла нет одноразовое действие), по завершению потоку "конец"... но сам обьект потока это не освобождает, для этого надо или явно Free сделать (подождав для гарантии завершения Execute (WaitFor)), или указать освобождать автоматом (FreeOnTerminate) что у меня и сделано.
> что при выходе из приложения метод Free не понадобится?
не понадобится, оно завершится и уничтожится гораздо раньше (меньше секунды после создания и запуска... но вообще возможны варинты ;)
kay (2006-04-12 17:04:00) [4]как убить тред в любой момент времени, чтобы от него ничего не осталось?
kay (2006-04-12 16:43:00) [5]
> пример вызова:
> TtcpThread.Create(false);
> и тоже все, ничего более, никаких извне вмешательств в компоненты
> потока, никаких закрытий, освождений... и т.д. это единственная
> (в этом случае) доступная тебе функция потока, его создание.
> (повесь на кнопку start)
я так понял при выходе их приложения вызывается метод Terminate? А переменная FreeOnTerminate говорит о том, что при выходе из приложения метод Free не понадобится?
kay (2006-04-12 16:34:00) [6]я просто хочу сделать нормальное завершение работы программы при выполнении подключении к серверу.
Сергей М. (2006-04-12 16:34:00) [7]
> чтобы постоянно не освобождать память
Что значит "постоянно" ? Какую память ?
> при выходе
При каком "выходе" ? Выходе откуда ?
sniknik (2006-04-12 16:34:00) [8]> ну извиняйте, раньше с тредами тесно не связывался.
твой пример, как он должен быть (хотя так и не понял зачем он...)
unit thread;
interface
uses Classes, SysUtils, IdTCPClient, IdComponent;
type
TtcpThread = class(TThread)
private
tcpClient: TIdTCPClient;
msg: string;
procedure SendMessage;
procedure tcpClientStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String);
protected
procedure Execute; override;
end;
implementation
uses main;
procedure TtcpThread.SendMessage;
begin
ovpnRestarter.logAdd(msg);
end;
procedure TtcpThread.tcpClientStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String);
begin
msg:= AStatusText;
Synchronize(SendMessage);
end;
procedure TtcpThread.Execute;
begin
FreeOnTerminate:= true;
with TIdTCPClient.Create(nil) do
try
try
OnStatus:= tcpClientStatus;
Host:= 'www.google.com';
Port:= 80;
Connect();
except
on E: Exception do begin
msg:= E.Message;
Synchronize(SendMessage);
end;
end;
finally
Free;
end;
end;
end.
и все.
пример вызова:
TtcpThread.Create(false);
и тоже все, ничего более, никаких извне вмешательств в компоненты потока, никаких закрытий, освождений... и т.д. это единственная (в этом случае) доступная тебе функция потока, его создание. (повесь на кнопку start)
kay (2006-04-12 16:22:00) [9]ну извиняйте, раньше с тредами тесно не связывался.
а криэйшн опять поставил, чтобы постоянно не освобождать память, а освобождать тоько при выходе
Сергей М. (2006-04-12 16:19:00) [10]В целом - бардак в логике и в выборе инструментов/алгоритмов ее реализации.
Сергей М. (2006-04-12 16:18:00) [11]
> в execute то при этом уже нет
Зато появился Disconnect() сразу после Connect().
Ну и зачем нужна эта бестолковая логика ?
> лучше бы как у меня сделать по принципу
Про "как у тебя" (с учетом авторского вольного манипулирования возобновлением/приостановкой/уничтожением потока когда ему вздумается) я уже сказал - утечки неизбежны.
sniknik (2006-04-12 16:15:00) [12]> забыл, что есть 2 кнопик. start и stop
> tcp:TtcpThread;
> на запуске tcp.Resume;
> на stop:
> tcp.tcpClient.Disconnect;
а смысл? "на stop" конект уже проверится и "отвалится" (execute кончится), что ты вообще хочеш сделать?
sniknik (2006-04-12 16:08:00) [13]> при завершении приложения:
> tcp.tcpClient.Disconnect;
> tcp.Free;
тут тебе надо не tcp.tcpClient.Disconnect; делать (что неправильно, и вообще Disconnect лишний), а tcp.WaitFor; ставить.
а лучше FreeOnTerminate в создании установить в true и "забыть" о потоке сразу после создания... а то иначе смысл самого потока теряеш.
и потом убрать прямые вызовы из другого потока.
> ovpnRestarter.logAdd(AStatusText);
сделать через синхронизацию. (сообщения/критическую секцию)
> И опять вижу при этом в [23]
но в execute то при этом уже нету ;), все нормально тут с с созданием (лучше бы как у меня сделать по принципу... но и так пойдет).
Сергей М. (2006-04-12 16:00:00) [14]Ну нельзя же так бессовестно врать !
Цитирую тебя :
> я его уже убрал
И опятьвижу при этом в [23]
> constructor TtcpThread.Create;
> begin
> inherited Create(true);
> tcpClient := TIdTCPClient.Create(nil);
> end;
kay (2006-04-12 15:53:00) [15]забыл, что есть 2 кнопик. start и stop
tcp:TtcpThread;
на запуске tcp.Resume;
на stop:
tcp.tcpClient.Disconnect;
kay (2006-04-12 15:26:00) [16]блин. действительно не всё так гладко.
значит объясняю как всё есть. при создании формы
tcp:=TtcpThread.Create;
при завершении приложения:
tcp.tcpClient.Disconnect;
tcp.Free;
далее сам тред:
unit thread;
interface
uses
Windows, SysUtils, Classes, IdTCPClient, IdComponent;
type
TtcpThread = class(TThread)
private
procedure tcpClientStatus(ASender: TObject; const AStatus: TIdStatus;
const AStatusText: String);
protected
procedure Execute; override;
public
tcpClient: TIdTCPClient;
destructor Destroy; override;
constructor Create;
end;
implementation
uses main;
constructor TtcpThread.Create;
begin
inherited Create(true);
tcpClient := TIdTCPClient.Create(nil);
end;
//******************************************************************************
destructor TtcpThread.Destroy;
begin
tcpClient.Free;
inherited;
end;
//******************************************************************************
procedure TtcpThread.Execute;
begin
try
tcpClient.OnStatus:=tcpClientStatus;
tcpClient.Host:='www.google.com';
tcpClient.Port:=80;
tcpClient.Connect();
tcpClient.Disconnect();
except
on E: Exception do
begin
ovpnRestarter.logAdd(E.Message);
end;
end;
end;
//******************************************************************************
procedure TtcpThread.tcpClientStatus(ASender: TObject;
const AStatus: TIdStatus; const AStatusText: String);
begin
ovpnRestarter.logAdd(AStatusText);
end;
//******************************************************************************
end.
вроде всё нормально, но иногда возникает зависон все системы. проц на 100% загружен. не понимаю в чём проблема. при вызове метода tcp.tcpClient.Disconnect; в треде возникает Exception и все ошибки обрабатываются.
Сергей М. (2006-04-12 14:33:00) [17]
> тред завершает работу - и далее всё по маслу
Далеко не "по маслу".
Вызывая в другом треде тот самый Disconnect ты провоцируешь исключительную ситуацию в треде, "висящем" на блокирующем коннекте, и никак не обрабатываешь ее при этом.
kay (2006-04-12 14:27:00) [18]я сначала DIsconnect делаю, тред завершает работу - и далее всё по маслу
Сергей М. (2006-04-12 14:25:00) [19]И тем не менее принудительное терминирование "висящего" треда (способ, выбранный тобой) - крайний вариант, которого всегда следует избегать.
kay (2006-04-12 14:06:00) [20]я его уже убрал, это первая версия была. всем спасибо. тему можно закрывать.