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

Вниз

Проблема с потоками   Найти похожие ветки 

 
Buzzik ©   (2010-04-06 18:56) [0]

Пишу программу, для проверки работоспособности большого количества комутаторов, по средством пинг. Чтобы приложение не подвисало начал использовать потоки. И все бы хорошо, если опрашиваемых комутаторов не много, но если их около сотни и больше, и многии из них лежат, то когда идет ожидание ответа - программа начинает подвисать. Причем загрузка проца около 10%-15%.

в  procedure TNewThread.Execute;
у меня идет стандартная посылка пакета
   IcmpSendEcho(hIP,
                destAddress.S_addr,
                @pingBuffer,
                sizeof(pingBuffer),
                Nil,
                pIpe,
                sizeof(icmp_echo_reply) + sizeof(pingBuffer),
                Timeout);

и результат идет в Synchronize(UpdateGrid);
В которой собственно изменения идут в vlc.

По таймеру у меня идет запуск цикла потоков
if     tr_on_=false then  //Проверяю закончился ли прошлый  
                                            //таймерный цикл
for i:=0 to form1.NextGrid1.RowCount-1 do
begin
   if  form1.NextGrid1.CellByName["Enabled",i].AsBoolean=true then begin
Delay(1);
Application.ProcessMessages;
host_2:= form1.NextGrid1.CellByName["IP",i].AsString;

colgrid:=i;

 NewThread:=TNewThread.Create(true);
 NewThread.FreeOnTerminate:=true;
 NewThread.Priority:=tpLower;
 NewThread.Resume;
// delay(10);
end;


Скорее всего подвисание происходит когда выполняеться IcmpSendEcho, пакет не проходит и идет собственно Timeout.
Подскажите, пожалуйста  как избежать подвисания интерфейса программы.
Или как правильно организовать работу данной задачи.


 
Игорь Шевченко ©   (2010-04-06 19:28) [1]

код потока в студию


 
Buzzik ©   (2010-04-06 20:08) [2]

procedure TNewThread.Execute;
var
   hIP : THandle;
   pingBuffer : array [0..31] of Char;
   pIpe : ^icmp_echo_reply;
   wVersionRequested : WORD;
   lwsaData : WSAData;
   error : DWORD;
   destAddress : In_Addr;
//    i: integer;
   IPReply: string;    pHostEn : PHostEnt;

begin
// delay(100);
  tr_on_:=true;
  vi_:=colgrid;
  msg:="";
  host_:=host_2;
  hIP := IcmpCreateFile();
  pHostEn := gethostbyname(pchar(host_));

   if not Assigned(pHostEn) then
   begin
     msg := "Reqested Timed out.";
     Synchronize(UpdateGrid);  Exit;
   end;

   destAddress := PInAddr(pHostEn^.h_addr_list^)^;

   GetMem( pIpe,
           sizeof(icmp_echo_reply) + sizeof(pingBuffer));
   pIpe.Data := @pingBuffer;
   pIpe.DataSize := sizeof(pingBuffer);

   wVersionRequested := MakeWord(1,1);
   error := WSAStartup(wVersionRequested,lwsaData);
   if (error <> 0) then
   begin
        msg := "Reqested Timed out.";

   end;
          msg3:=  IntToStr(LoByte(LoWord(pIpe^.Address)))+"."+
              IntToStr(HiByte(LoWord(pIpe^.Address)))+"."+
              IntToStr(LoByte(HiWord(pIpe^.Address)))+"."+
              IntToStr(HiByte(HiWord(pIpe^.Address)));

       Timeout:=(2000);
//CriticalSection.Enter;

  if error=0 then begin

   IcmpSendEcho(hIP,
                destAddress.S_addr,
                @pingBuffer,
                sizeof(pingBuffer),
                Nil,
                pIpe,
                sizeof(icmp_echo_reply) + sizeof(pingBuffer),
                Timeout);

                end;
//  CriticalSection.Leave;

   error := GetLastError();
   if (error <> 0) then
   begin
        msg := "Reqested Timed out.";

   end;
            if error=0 then begin

   IPReply := IntToStr(LoByte(LoWord(pIpe^.Address)))+"."+
              IntToStr(HiByte(LoWord(pIpe^.Address)))+"."+
              IntToStr(LoByte(HiWord(pIpe^.Address)))+"."+
              IntToStr(HiByte(HiWord(pIpe^.Address)));

            if error=0 then
   msg:=  "Reply from "+  IPReply
               + " bytes="+
                   IntToStr(sizeof(pingBuffer)) +
                   " time="
               +
               IntToStr(pIpe.RTTime)+" ms"
               else msg:= "Reqested Timed out.";

               if (LoByte(LoWord(pIpe^.Status)))=250 then
              msg:= "Destination host unreachable." ;

                   end;
 if pos(msg3,msg)<>0 then msg:="Destination host unreachable." ;{сравнение IP хоста с IP отвечающей железяки}

                msg:= datetimetostr(now)+" "+msg;

  Synchronize(UpdateGrid);

IcmpCloseHandle(hIP);
WSACleanup();
FreeMem(pIpe);

end;


 
DVM ©   (2010-04-06 20:23) [3]


> Buzzik ©  

она у тебя виснет не потому что коммутаторы недоступны, а потому что ты постоянно создаешь разрушаешь потоки.

Нахрена их уничтожать то?


 
Игорь Шевченко ©   (2010-04-06 20:28) [4]


>   Synchronize(UpdateGrid);


еще эту часть - UpdateGrid


 
Buzzik ©   (2010-04-06 20:49) [5]


> DVM

Может быть, просто замеченно что именно в том месте подвисает.
Покопаю в этом направлении.


> Игорь Шевченко

Проверено опытным путем, что если закаментить весь вывод, то подвисание всеравно происходит

procedure TNewThread.UpdateGrid;
var //i, j:integer;
str:string;
begin

if (pos("Reqested Timed out.", msg)=0)and(pos("Destination host unreachable.", msg)=0) then begin
if form1.NextGrid1.CellByName["Status",vi_].AsString="Down" then
form1.NextGrid1.CellByName["Log",vi_].AsString:=
datetimetostr(now)+" "+form1.NextGrid1.CellByName["IP",vi_].AsString
+" is UP"+#13+
form1.NextGrid1.CellByName["Log",vi_].AsString;

form1.NextGrid1.CellByName["Status",vi_].AsString:="OK";
form1.NextGrid1.CellByName["Status", vi_].Color:=clWhite;

form1.NextGrid1.CellByName["Kol_vo_p",vi_].AsInteger:=0;

end else Begin
form1.NextGrid1.CellByName["Kol_vo_p",vi_].AsInteger:=
form1.NextGrid1.CellByName["Kol_vo_p",vi_].AsInteger+1;
if  (form1.NextGrid1.CellByName["Status",vi_].AsString="OK")or
(form1.NextGrid1.CellByName["Status",vi_].AsString="Unknown")or
(form1.NextGrid1.CellByName["Status",vi_].AsString="Disabled")
 then begin
form1.NextGrid1.CellByName["Status",vi_].AsString:="Some problems";

form1.NextGrid1.CellByName["Status", vi_].Color:=clYellow;

                                                end;
if (form1.NextGrid1.CellByName["Kol_vo_p",vi_].AsInteger>form1.ploss_spin.value-1)
then begin

if form1.NextGrid1.CellByName["Status",vi_].AsString="Some problems"  then

if form1.NextGrid1.CellByName["Kol_vo_p",vi_].AsInteger=form1.ploss_spin.value then begin
form1.NextGrid1.CellByName["Status",vi_].AsString:="Down";
form1.NextGrid1.CellByName["Status", vi_].Color:=clRed;

form1.NextGrid1.CellByName["Log",vi_].AsString:=
datetimetostr(now)+" "+form1.NextGrid1.CellByName["IP",vi_].AsString
+" is DOWN"+#13+
form1.NextGrid1.CellByName["Log",vi_].AsString;

if Form1.Alert_CheckBox.Checked=true then
if Alert_window.Visible=false then begin
ShowWindow(Alert_window.Handle, SW_RESTORE);
row_down:=vi_;
Alert_window.timer2.Enabled:=true;
Alert_window.Label1.Caption:=
form1.NextGrid1.CellByName["Host",vi_].AsString+" is DOWN"+#13;
//+
                                   end;  end;

if  form1.NextGrid1.CellByName["Alarm_en", vi_].AsBoolean=true then
                            begin

if form1.NextGrid1.CellByName["Kol_vo_p",vi_].AsInteger=form1.ploss_spin.value then begin

str:=(form1.NextGrid1.CellByName["Alarm", vi_].AsString);
 if  BASS_ChannelIsActive(Channel)<>BASS_ACTIVE_PLAYING then
 if mute<>true then begin
 try
BASS_ChannelStop(Channel);
Channel := BASS_StreamCreateFile(FALSE, PChar(str), 0, 0, 0);
if form1.NextGrid1.CellByName["Loop_sound", vi_].AsBoolean<>false then
BASS_ChannelFlags(channel, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP)  // set LOOP flag
else
BASS_ChannelFlags(channel, 0, BASS_SAMPLE_LOOP); // remove LOOP flag

BASS_ChannelPlay(Channel, true);
    except  end;
                              end;
                     end;

        end;

                                                                       end;
        end;
if form1.NextGrid1.CellByName["Enabled",vi_].AsBoolean=false
then form1.NextGrid1.CellByName["Status",vi_].Color:=clGray;

tr_on_:=false;
end;


 
DVM ©   (2010-04-06 21:01) [6]


> Buzzik ©   (06.04.10 20:49) [5]
> > DVM
> Может быть, просто замеченно что именно в том месте подвисает.
> Покопаю в этом направлении.

Ты лучше сделай по другому.

1) Выкинь таймер, не нужен он.
2) Создаешь нужное число потоков по числу коммутаторов.
3) Циклы делаешь в самих потоках.
4) Пусть потоки извещают главный поток с помощью сообщений


 
Дмитрий Белькевич   (2010-04-06 22:53) [7]

>form1.NextGrid1

with напиши. Глаза болят.


 
Дмитрий Белькевич   (2010-04-06 23:02) [8]


> with напиши. Глаза болят.


Да и вообще - к форме из треда лучше не лезть. Пусть форма сообщения от тредов обрабатывает.

Но with напиши даже в форме.

И вот это: CellByName["Kol_vo_p",vi_] лучше один раз посчитать как-то типа CellKolVol := CellByName["Kol_vo_p",vi_] (если, правда, CellByName возвращает какой-нибудь TCell) и уже потом по всему методу к CellKolVol обращаться.

Как есть - больно глазам и компьютеру.


 
Loginov Dmitry ©   (2010-04-06 23:22) [9]

Вот что хотелось бы добавить:

Synchronize(UpdateGrid);
следует убрать.

Если 100 потоков почти одновременно его вызовут, тормозища будут страшные (причем и потоки будут висеть - друг друга ждать). Вместо этого следует разработать структуру для временного хранения полученных данных.

Бросить на форму таймер, который будет несколько раз в секунду считывать информацию их этой структуры и отображать ее на сетке. При этом структура должна быть "потокобезопасной". Плюс все это можно неслабо оптимизировать (например не обновлять ячейку, если ее значение не изменилось).


 
Slym ©   (2010-04-07 10:57) [10]

Удалено модератором


 
Buzzik ©   (2010-04-07 11:55) [11]


> DVM

Спасибо, помогло, работает без тормозов, хоть я и не дошел до сообщений.

Всем спасибо, за помощь в решении проблемы.



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

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

Наверх




Память: 0.49 MB
Время: 0.076 c
15-1263939469
Маша
2010-01-20 01:17
2010.08.27
Странная задачка


15-1270305381
Игорь Шевченко
2010-04-03 18:36
2010.08.27
Microsoft заботится о нас. Иногда даже чересчур


2-1271223708
Дмитрий С
2010-04-14 09:41
2010.08.27
Как вернуть Скролл на прежнее место.


2-1268839389
Knob
2010-03-17 18:23
2010.08.27
Командная строка


4-1236650462
YuS
2009-03-10 05:01
2010.08.27
Как узнать загрузку процессора?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский