Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.09.14;
Скачать: [xml.tar.bz2];

Вниз

Пинг   Найти похожие ветки 

 
DeeNamid ©   (2008-08-04 12:48) [0]

Вопрос такой, делаю пять потоков которые пингуют каждый свою машину и выводять результаты на пять окон, проблема с icmp-компонентом. Все пять потоков толкутся около icmp.ping() и результаты пинга искажаются.
Код примерно такой:

procedure Tping1.Execute;
begin
 while not (terminated or application.Terminated) do begin
//EnterCriticalSection(CS);
 res:=ping_func(ip_addres);
//LeaveCriticalSection(CS);
 synchronize(print_res);
 end;
end;

function Tping1.ping_func(host:string):integer;
var i,failed:integer;
begin
 icmp.ReceiveTimeout:=3000;
 icmp.Host:=host;
 icmp.Ping();
 if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
   ping_func:=icmp.ReplyStatus.MsRoundTripTime
  else
   ping_func:=0;
end;

Когда ставишь критическую секцию результаты отображаются адекватно, но пока один поток пингует все остальные его ждут. Как сделать так что бы все пинговалось независимо друг от друга?


 
Сергей М. ©   (2008-08-04 12:53) [1]


> Как сделать так что бы все пинговалось независимо друг от
> друга?
>


Каждый поток должен создавать и юзать свой собственный экз-р класса TIdICMP.


 
DeeNamid ©   (2008-08-04 12:54) [2]

Так и сделано вот полный вид execut"a

procedure Tping1.Execute;
var b:boolean;i:integer;
begin
 FreeOnTerminate:=true;
 b:=true;
 icmp:=TIdIcmpClient.Create(nil);
 while not (terminated or application.Terminated) do begin
EnterCriticalSection(CS);
 res:=ping_func(ip_addres);
LeaveCriticalSection(CS);
 synchronize(print_res);
 end;
 icmp.Destroy;
end;


 
DeeNamid ©   (2008-08-04 12:55) [3]

Так и сделано вот полный вид execut"a

procedure Tping1.Execute;
var b:boolean;i:integer;
begin
 FreeOnTerminate:=true;
 b:=true;
 icmp:=TIdIcmpClient.Create(nil);
 while not (terminated or application.Terminated) do begin
EnterCriticalSection(CS);
 res:=ping_func(ip_addres);
LeaveCriticalSection(CS);
 synchronize(print_res);
 end;
 icmp.Destroy;
end;


 
Сергей М. ©   (2008-08-04 12:58) [4]


> Так и сделано


Нет, сделано не так.

Создавать-то ты создаешь по экземпляру на каждый поток, а юзаешь в каждом потоке один и то же экз-р.


 
DeeNamid ©   (2008-08-04 13:02) [5]

Недопонял. Как юзать разные экземпляры?


 
Сергей М. ©   (2008-08-04 13:04) [6]

function Tping1.ping_func(ICMP: TIdICMP; host:string):integer;
var i,failed:integer;
begin
icmp.ReceiveTimeout:=3000;
icmp.Host:=host;
icmp.Ping();
if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
  ping_func:=icmp.ReplyStatus.MsRoundTripTime
 else
  ping_func:=0;
end;

procedure Tping1.Execute;
var
  ICMPInstance: TIdICMP;
begin
..
ICMPInstance:=TIdIcmpClient.Create(nil);
try
  while not (terminated or application.Terminated) do begin
    res:=ping_func(ICMPInstance, ip_addres);
    synchronize(print_res);
  end;
finally
  ICMPInstance.Free;
end;
..
end;


 
antonn ©   (2008-08-04 13:20) [7]

Ого, Сергей показал готовый код, где то здесь подвох! %)


 
Сергей М. ©   (2008-08-04 13:42) [8]


> antonn ©   (04.08.08 13:20) [7]


Подвох не у меня , а у автора - область видимости ид-ра icmp он не удосужился уточнить)


 
Anatoly Podgoretsky ©   (2008-08-04 13:59) [9]

Да он вообще мало информации предоставил, зато он предоставил нам возможность проявиться телепатические способности.


 
DeeNamid ©   (2008-08-04 14:22) [10]

Ну смотрите тады ))
Главная форма:

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   ComboBox1: TComboBox;
   Panel1: TPanel;
   Label7: TLabel;
   Label8: TLabel;
   Label9: TLabel;
   Label10: TLabel;
   Label11: TLabel;
   Label12: TLabel;
   Memo2: TMemo;
   Memo3: TMemo;
   Memo4: TMemo;
   Memo5: TMemo;
   Memo6: TMemo;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   ping1,ping2,ping3,ping4,ping5: Tping;
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
ping1:=Tping.Create("93.158.134.3",1);
ping2:=Tping.Create("172.21.161.34",2);
ping3:=Tping.Create("172.21.61.44",3);
ping4:=Tping.Create("10.61.1.126",4);
ping5:=Tping.Create("172.21.61.46",5);
 ping1.Resume;
 ping2.Resume;
 ping3.Resume;
 ping4.Resume;
 ping5.Resume;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
try
  ping1.Terminate;
  ping2.Terminate;
  ping3.Terminate;
  ping4.Terminate;
  ping5.Terminate;
except
end;
end;

Unit2:

type
 Tping = class(TThread)
 private
   memo_num:integer;ip_addres:string;
   res:integer;res_str:string;
 protected
   procedure Execute; override;
   function ping_func(icmp:TIdIcmpClient;host:string):integer;
   procedure print_res;
 public
   constructor create(ip_addr:string;i:integer);
 end;
var CS:TRTLCriticalSection;
implementation
uses Unit1;

function Tping.ping_func(icmp:TIdIcmpClient;host:string):integer;
begin
 icmp.ReceiveTimeout:=3000;
 icmp.Host:=host;
 icmp.Ping();
 if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
   ping_func:=icmp.ReplyStatus.MsRoundTripTime
  else
   ping_func:=0;
end;

procedure Tping.Execute;
var icmp: TIdIcmpClient;
begin
 FreeOnTerminate:=true;
 icmp:=TIdIcmpClient.Create(nil);
 while not (terminated or application.Terminated) do begin
//EnterCriticalSection(CS);
 res:=ping_func(icmp,ip_addres);//мне кажется здесь заморочка с res
//LeaveCriticalSection(CS);
 sleep(0);
 synchronize(print_res);
 end;
 icmp.Destroy;
end;

procedure Tping.print_res;
begin
if res>0 then res_str:="&#194;&#240;&#229;&#236;&#255; &#228;&#238; &#245;&#238;&#241;&#242;&#224;: "+inttostr(res)+"ms" else res_str:="&#207;&#240;&#229;&#226;&#251;&#248;&#229;&#237; &#232;&#237;&#242;&#229;&#240;&#226;&#224;&#235; &#238;&#230;&#232;&#228;&#224;&#237;&#232;&#255;";
case memo_num of
 1: Form1.memo2.Lines.add(res_str);
 2: Form1.memo3.Lines.add(res_str);
 3: Form1.memo4.Lines.add(res_str);
 4: Form1.memo5.Lines.add(res_str);
 5: Form1.memo6.Lines.add(res_str);
end;
Form1.memo1.lines.add("&#207;&#238;&#242;&#238;&#234; &#237;&#238;&#236;&#229;&#240;: "+inttostr(memo_num));
Form1.Memo1.Lines.Add(res_str);
end;

constructor Tping.create(ip_addr: string;i:integer);
begin
ip_addres:=ip_addr;
memo_num:=i;
inherited create(true);
end;

initialization
 InitializeCriticalSection(CS);
end.

Как-то так. Сделал как ты сказал, ничего не изменилось.


 
Dennis I. Komarov ©   (2008-08-04 14:25) [11]

> [7] antonn ©   (04.08.08 13:20)

Значок видишь?


 
DeeNamid ©   (2008-08-04 14:31) [12]

Ты о чем?


 
DeeNamid ©   (2008-08-04 14:58) [13]

Куда-то все пропали... Помогите прояснить проблему. Почему не получается сделать так что-бы пять потоков независимо друг от друга корректно работали.


 
Сергей М. ©   (2008-08-04 15:47) [14]


> DeeNamid ©   (04.08.08 14:58) [13]


А в чем, по-твоему, выражается их "зависимость друг от друга", в данный момент, т.е. при реализации, приведенной тобой в [10] ?


 
DeeNamid ©   (2008-08-04 16:01) [15]

Зависимость заключается в том что все пять потоков выводят на экран одни и те же значения.
Есть пять потоков и пять компонентов memo, на которые должны выводиться результаты пинга. Если использовать критическую секцию то все происходит нормально, то есть в каждом окошке отображаются корректные результаты. Но в этом случае пока пингует один поток, остальные его ждут, а это не гуд. Если же закомментировать эту секцию, то происходит следующее - все окошки отображают одни и те же цифры, при чем при отладке в watch"е видно что в процедуре print_res сам res для всех потоков имеет одинаковое значение. Вот в этом и вопрос - почему так происходит что res открыт для всех потоков, если он является локальной переменной класа TPing?


 
Сергей М. ©   (2008-08-04 16:13) [16]


> res для всех потоков имеет одинаковое значение


Какое конкретно ?


 
DeeNamid ©   (2008-08-04 16:16) [17]

Ну к примеру 154, тогда на вывод получается:
Время до хоста: 154 ms
и так пять раз на все окна.


 
Medbe}I{onok XML ©   (2008-08-04 16:22) [18]

результат пинга число?

убрать всю эту ахинею. после окончания пинга и получения результата посылать главному окну сообщение, результат передавать в WParam или LParam


 
DeeNamid ©   (2008-08-04 16:25) [19]

Что-то как-то ты категорично вещаешь. Объясни подробнее плиз что такое

> результат передавать в WParam или LParam?


 
Сергей М. ©   (2008-08-04 16:25) [20]

А ты вообще понимаешь, что означает и как вычисляется св-во MsRoundTripTime ?

Оно никаким боком не относится к "время до хоста".


 
DeeNamid ©   (2008-08-04 16:27) [21]

Ладно это не важно, мне надо понять в чем проблема, почему локальную переменную имеют все подряд?


 
Medbe}I{onok XML ©   (2008-08-04 16:28) [22]

procedure Tping.Execute;
var icmp: TIdIcmpClient;
begin
FreeOnTerminate:=true; //Это в конструктор убрать
icmp:=TIdIcmpClient.Create(nil);
while not (terminated or application.Terminated) do begin
res:=ping_func(icmp,ip_addres);
end;
icmp.Destroy;
PostMessage(fMainFormHandle,WM_MYPING_MSG,<fNumberForMemo>,LParam(res));
end;


 
Medbe}I{onok XML ©   (2008-08-04 16:29) [23]

fMainFormHandle (хендл окна с лежащим не ём мемом) и fNumberForMemo (в каком мемо рисовать результат) передавать конструктору вторичного потока.


 
Medbe}I{onok XML ©   (2008-08-04 16:31) [24]

Точнее так, если там надо пинговать пока рак не свистнет:

procedure Tping.Execute;
var icmp: TIdIcmpClient;
begin
FreeOnTerminate:=true; //Это в конструктор убрать
icmp:=TIdIcmpClient.Create(nil);
while not (terminated or application.Terminated) do begin
res:=ping_func(icmp,ip_addres);
PostMessage(fMainFormHandle,WM_MYPING_MSG,<fNumberForMemo>,LParam
end;
icmp.Destroy;
(res));
end;


 
Сергей М. ©   (2008-08-04 16:32) [25]


> почему локальную переменную имеют все подряд?


Никто ее не "имеет")

С логикой в твоем коде все более-менее в порядке.

Пробуй пинговать хосты из разных концов Тырнета - получишь разные результаты.


 
DeeNamid ©   (2008-08-04 16:33) [26]

То есть,
constructor Tping.create(ip_addr: string;i:integer;fMainFormHandle;fNumberForMemo);
так? Номер мемо просто цифра? И где взять хендл ?


 
Medbe}I{onok XML ©   (2008-08-04 16:36) [27]

constructor Tping.create(ip_addr: string;fMainFormHandle : HWND;fNumberForMemo : integer);


 
Medbe}I{onok XML ©   (2008-08-04 16:38) [28]

procedure TForm1.Button1Click(Sender: TObject);
begin

ping1:=Tping.Create("93.158.134.3",Handle,1);
ping2:=Tping.Create("172.21.161.34",Handle,2);
ping3:=Tping.Create("172.21.61.44",,Handle,3);
ping4:=Tping.Create("10.61.1.126",Handle,4);
ping5:=Tping.Create("172.21.61.46",Handle,5);


 
Сергей М. ©   (2008-08-04 16:41) [29]


> Medbe}I{onok XML ©   (04.08.08 16:38) [28]


Ну и какая нафих разница ? Что, от вида синхронизации зависит трип-тайм ?)


 
Medbe}I{onok XML ©   (2008-08-04 16:41) [30]

я его спасаю от ужасов print_res


 
Сергей М. ©   (2008-08-04 16:43) [31]


> спасаю от ужасов print_res
>


На якобы имеющее место "проблему" эти "ужасы" никак не влияют)


 
Medbe}I{onok XML ©   (2008-08-04 16:44) [32]

к тому же будет побочный положительный эффект:
нитка и главная форма потеряют имеющуюся чудовищную взаимозависимость между собой и отлаживать все станет проще.


 
Medbe}I{onok XML ©   (2008-08-04 16:45) [33]

На якобы имеющее место "проблему" эти "ужасы" никак не влияют)

Влияют на скорость понимания что они и правда не влияют.
:)


 
DeeNamid ©   (2008-08-04 16:54) [34]


> Сергей М.


Смотри как интересно получается
memo1:
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 109ms
Время до хоста: 94ms
Время до хоста: 594ms
memo2:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 125ms
Время до хоста: 94ms
Время до хоста: 579ms
memo3:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 125ms
Время до хоста: 94ms
Время до хоста: 579ms
memo4:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 125ms
Время до хоста: 94ms
Время до хоста:579ms
memo5:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 109ms
Время до хоста: 78ms
Время до хоста: 579ms
Причем memo1 это yandex.ru а остальные наш филиал через vpn.
А вот что будет если внести ping_func в критическую секцию
memo1:
Превышен интервал ожидания
Время до хоста: 1454ms
Время до хоста: 1218ms
Время до хоста: 1469ms
Время до хоста: 1703ms
Время до хоста: 1422ms
memo2:
Время до хоста: 922ms
Время до хоста: 531ms
Время до хоста: 875ms
Превышен интервал ожидания
Время до хоста: 593ms
Время до хоста: 344ms
memo3:
Время до хоста: 93ms
Время до хоста: 125ms
Время до хоста: 171ms
Время до хоста: 110ms
Время до хоста: 297ms
memo4:
Время до хоста: 94ms
Время до хоста: 922ms
Время до хоста: 188ms
Время до хоста: 265ms
Время до хоста: 297ms
Время до хоста: 125ms
memo5:
Время до хоста: 437ms
Превышен интервал ожидания
Время до хоста: 141ms
Время до хоста: 313ms
Время до хоста: 94ms
Время до хоста: 125ms
Другое дело правда?


 
Сергей М. ©   (2008-08-04 17:08) [35]


> memo1 это yandex.ru а остальные наш филиал через vpn


И что ?

Я видижу, что цифирь для Яндекса отличается от цифири для вашей vpn.

А ты утверждал, что цифирь одинакова для любых хостов )


 
DeeNamid ©   (2008-08-04 17:16) [36]

Ну ты же видишь разницу в первом случае и во втором? А получилось так просто потому что я всего несколько строк написал, если посмотреть дальше будет видно сходство. Оно и правда не точно идентично, но ведь ясно же что какой-то косяк есть. Я настаиваю на том что после внесения результата в res и до вывода на экран, значение res искажается каким-то другим потоком. И хочу понять почему так происходит? Может есть какие-то другие методы хранения и защиты локальных переменных (кроме threadvar и того как сделано у меня)?


 
Medbe}I{onok XML ©   (2008-08-04 17:24) [37]

Я настаиваю на том что после внесения результата в res и до вывода на экран, значение res искажается каким-то другим потоком.

Это точно метапоток из галактик-футбалл.


 
DeeNamid ©   (2008-08-04 17:25) [38]

Точнее даже не так. Посмотри что получается:

function Tping.ping_func(icmp:TIdIcmpClient;host:string):integer;
var i,failed:integer;
begin
 icmp.ReceiveTimeout:=3000;
 icmp.Host:=host;
EnterCriticalSection(CS); //!
 icmp.Ping();
LeaveCriticalSection(CS);//!
 if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
   ping_func:=icmp.ReplyStatus.MsRoundTripTime
  else
   ping_func:=0;
end;

Так тоже все работает нормально. Дело в самом пинге. И теперь я вообще ничего не понимаю. Хотя и раньше мало что понимал ))


 
Medbe}I{onok XML ©   (2008-08-04 17:25) [39]

да причем так хитро искажается, что везде одинаково.


 
DeeNamid ©   (2008-08-04 17:26) [40]


> Medbe}I{onok XML


Харе прикалываться :)) Посмотри на 38 пост, с пингом какие-то замороки.



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.09.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.042 c
2-1217390260
apic
2008-07-30 07:57
2008.09.14
сокрытие файлов и папок


4-1196339588
sergen
2007-11-29 15:33
2008.09.14
Нужен help


15-1216894108
Кактус
2008-07-24 14:08
2008.09.14
SQL


2-1217606385
InsanI
2008-08-01 19:59
2008.09.14
Ввод текста в другой программе


4-1196619757
Belorus
2007-12-02 21:22
2008.09.14
CreateFiber





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский