![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Потоки и пинг [D7, WinXP]
S46E © (2006-07-18 08:36:00)Задача: паралельный пинг всех ip в списке Hosts без зависания программы.
Код который имеется:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
IdIcmpClient;
type
TForm1 = class(TForm)
Icmp: TIdIcmpClient;
Button1: TButton;
hosts: TMemo;
Log: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TNew = class(TThread)
private
n: integer;
procedure AddStr;
{ Private declarations }
protected
procedure Execute; override;
end;
var
Form1: TForm1;
New, New2: TNew;
implementation
{$R *.dfm}
procedure TNew.Execute;
begin
Synchronize(AddStr);
end;
procedure TNew.AddStr;
begin
Form1.Icmp.Host:=Form1.Hosts.Lines[n];
Form1.Icmp.Ping('');
Form1.Log.Lines.Add('Ping '+Form1.Icmp.ReplyStatus.FromIpAddress+'______RTTime: '+InttoStr(Form1.Icmp.ReplyStatus.MsRoundTripTime)+'_______TTL: '+InttoStr(Form1.Icmp.ReplyStatus.TimeToLive));
end;
{---}
procedure TForm1.Button1Click(Sender: TObject);
begin
New := TNew.Create(true);
New.FreeOnTerminate := true;
New.Priority := tpNormal;
New2 := TNew.Create(true);
New2.FreeOnTerminate := true;
New2.Priority := tpNormal;
New.n:=0;
New2.n:=1;
New.Resume;
New2.Resume;
end;
end.
S46E (2006-07-21 14:46:00) [21]
...
TPingThread=class(Tthread)
private
FHost: String;
FResult: String;
function Pinghost: string;
protected
procedure Execute; override;
public
constructor Create(Host: String);
end;
...
procedure TForm1.Button1Click(Sender: TObject);
var
N: integer;
begin
For N:=0 to Hosts.Lines.Count-1 do
begin
with TPingThread.Create(Hosts.Lines[N]) do
begin
OnTerminate := PingTerminated;
//Resume;
end;
end;
end;
{ TPingThread }
constructor TPingThread.Create(Host: String);
begin
inherited Create(True);
FreeOnTerminate := True;
FHost := Host;
Resume;
end;
procedure TPingThread.Execute;
begin
FResult := PingHost;
end;
function TPingThread.Pinghost: string;
var
Pinger: TIdIcmpClient;
begin
Result := 'Îøèáêà';
Pinger := TIdIcmpClient.Create(nil);
Pinger.Host := FHost;
Pinger.Ping('');
Result:='Ïèíã '+FHost+'______Âðåìÿ îòâåòà: '+InttoStr(Pinger.ReplyStatus.MsRoundTripTime)+' ìñ_______TTL: '+InttoStr(Pinger.ReplyStatus.TimeToLive);
if Pinger.ReplyStatus.FromIpAddress='0.0.0.0' then Result:=FHost+' íå îòâå÷àåò (òàéì-àóò 5 ñåêóíä)';
end;
procedure TForm1.PingTerminated(Sender: TObject);
var
PR: TPingThread;
begin
PR := TPingThread(Sender);
Log.Lines.Add(PR.FResult);
end;
...
Не очень качественно пингует мертвые хосты. Если в списке помимо реал-мертвых есть хоть один реал-живой то в логе все оказываются живыми. Если нету - то все ок. Т.е. достаточно одного реал-живого хоста в списке - выводит всех как живых без всяких раздумий. Раздумия идут если все реал-мертвые, 5 сек:)
Мне кажется или в этом коде много масла масленого?
S46E (2006-07-21 14:39:00) [22]А если
OnTerminate := PingTerminated;
запихать собстно в Create?
Пусик (2006-07-21 14:17:00) [23]
> isasa © (21.07.06 10:29) [52]
> Пусик © (21.07.06 09:49) [51]А присваивать событие, при
> работающем потоке, логично?А вдруг не успеет?
Согласна, упустила из виду.
Хотя в любом случае обработчик успеет в данном случае присоиться раньше, но для общего случая лучше не использовать его так.
Может даже лучше будет изменить(или добавить еще один) конструктор, и в нем передавать адрес обработчика этого события.
StriderMan (2006-07-21 12:14:00) [24]
> !_SM_! (21.07.06 00:05) [47]
> Оказывается, всамом деле, если в PingTerminate делать Free
> Sender'у то все виснет.
Я думаю происходит следующее:
деструкторе TThread вызывает обработчик OnTerminate а в нем опять вызывается деструктор. получается бесконечная рекурсия
S46E (2006-07-21 11:24:00) [25]А, понял. Блин..
S46E (2006-07-21 11:23:00) [26]Есть мнение что OnTerminate это обработчик который срабатывает после того как пинг сам добровольно завершится, на то он и 'On':)
isasa (2006-07-21 10:29:00) [27]Пусик © (21.07.06 09:49) [51]
А присваивать событие, при работающем потоке, логично?
А вдруг не успеет?
with TPingThread.Create('10.0.0.1') do <- Тут уже запустили
begin <- А вот тут он уже завершился, быстро пинганул.
OnTerminate := PingTerminated;
end;
Пусик (2006-07-21 09:49:00) [28]>isasa ©
Сорри, невнимательно прочитала пост.
Не соглашусь, что перенести Resume из конструктора в основной поток - логичнее. Не видно в этом смысла.
Пусик (2006-07-21 09:44:00) [29]
> isasa © (21.07.06 09:07) [48]
> !_SM_! (21.07.06 00:05) [47]Оказывается, всамом деле,
> если в PingTerminate делать Free Sender'у то все виснет.
> Оно радо?FreeOnTerminate := True; ?procedure TForm1.Button1Click(Sender:
> TObject);begin with TPingThread.Create('10.0.0.1') do begin
> OnTerminate := PingTerminated; Resume; <- Перенести
> из Create сюда, так логичнее :) end;end;
OnTerminate возникает после иокончания выполнения поточной функции.
Resume-же как раз и позволяет начать выполнение этой функции. В обработчике события OnTerminate Resume просто бессмысленно выполнять.
isasa (2006-07-21 09:09:00) [30]Оно надо?
isasa (2006-07-21 09:07:00) [31]!_SM_! (21.07.06 00:05) [47]
Оказывается, всамом деле, если в PingTerminate делать Free Sender'у то все виснет.
Оно радо?
FreeOnTerminate := True; ?
procedure TForm1.Button1Click(Sender: TObject);
begin
with TPingThread.Create('10.0.0.1') do
begin
OnTerminate := PingTerminated;
Resume; <- Перенести из Create сюда, так логичнее :)
end;
end;
!_SM_! (2006-07-21 00:05:00) [32]
> StriderMan © (20.07.06 23:07) [46]
Спасибо.
И как же в таком случае экземпляр убить в другой подпрограмме
т.е. по нажатию кнопки он (поток) создается, а на свое (потока) завершение, в другом месте, как убить экземпляр. Ну это все из выше приведенного... Или это опять чушь?
Оказывается, всамом деле, если в PingTerminate делать Free Sender'у то все виснет.
StriderMan (2006-07-20 23:07:00) [33]
> А там, походу, и не надо Free делать, да и вооще наверное
> не надо его делать... так как переменная локальная то она
> убьется и память освабодится при выходе... Или не так?
нет не так. переменная убъется, а экземпляр класса останется в памяти.
!_SM_! (2006-07-20 20:43:00) [34]
> S46E © (20.07.06 17:52) [27]
> не помогает:(>> Пробовал вставлять TNew(Sender).Free в PingTerminate,
> не понимает синтаксис:)поправка: программа просто виснет.
> как и при TNew(Sender).Terminate
А там, походу, и не надо Free делать, да и вооще наверное не надо его делать... так как переменная локальная то она убьется и память освабодится при выходе... Или не так?
Пусик (2006-07-20 19:02:00) [35]В конструкторе забыла Resume:
constructor TPingThread.Create(Host: String);
begin
inherited Create(True);
FreeOnTerminate := True;
FHost := Host;
Resume;
end;
Пусик (2006-07-20 19:01:00) [36]>!_SM_!
Вот схематично код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TPingThread=class(Tthread)
private
FHost: String;
FResult: Boolean;
function Pinghost: Boolean;
protected
procedure Execute; override;
public
constructor Create(Host: String);
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
procedure PingTerminated(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
with TPingThread.Create('10.0.0.1') do
begin
OnTerminate := PingTerminated;
end;
end;
{ TPingThread }
constructor TPingThread.Create(Host: String);
begin
inherited Create(True);
FreeOnTerminate := True;
FHost := Host;
end;
procedure TPingThread.Execute;
begin
FResult := PingHost;
end;
function TPingThread.Pinghost: Boolean;
var
Pinger: TPinger;
begin
Result := False;
Pinger := TPinger.Create(nil);
Pinger.Host := FHost;
// ...
//здесь пингуем.
//if Ok then Result := True;
end;
procedure TForm1.PingTerminated(Sender: TObject);
var
PR: TPingThread;
begin
PR := TPingThread(Sender);
if PR.FResult
then Memo1.Lines.Add(PR.FHost+' OK')
else Memo1.Lines.Add(PR.FHost+' FAILED')
end;
end.
!_SM_! (2006-07-20 18:45:00) [37]>then ssory...
Sorry, then sorry...
!_SM_! (2006-07-20 18:18:00) [38]
> Да, просто "Sender.Free;"
then ssory...
S46E (2006-07-20 18:18:00) [39]>> Ну и тудаже
>> if (Sender is TNew) then Sender.Fre;
Ну и так же виснет=)
!_SM_! (2006-07-20 18:16:00) [40]
> isasa © (20.07.06 18:14) [37]
Ну и тудаже
if (Sender is TNew) then Sender.Fre;