Ir al contenido


Foto

Aplicación se congela al hacer Pings masivo


  • Por favor identifícate para responder
42 respuestas en este tema

#1 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 14 marzo 2009 - 04:52

Pues eso, tengo una aplicación que verifica si unos equipos (24) están activos o no a través del método ping, sucede que si muchos equipos están apagados o inactivos, la aplicación se congela (1 minuto a 1.5) hasta empezar el proceso, ¿cómo puedo evitar eso?. Estoy usando los Indy más especí­ficamente el TIdIcmpClient, dejo el código e imagen de la aplicación.

Saludos.


  • 0

#2 seoane

seoane

    Advanced Member

  • Administrador
  • 1.259 mensajes
  • LocationEspaña

Escrito 14 marzo 2009 - 05:08

Pues me temo que tendrás que usar threads.

Si implementas el ping dentro de un thread puedes realizar 10, 20 o incluso 30 pings simultáneos. Además mientras se están realizando tu aplicación no parecerá congelada.
  • 0

#3 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 14 marzo 2009 - 05:10

Gracias Seoane, lo de hacerlo con Hilos es interesante, la cuestión es que no sé ni pí­o de Threads, pues si esa es la solución voy a googlear un poco sobre la programación con threads.

Saludos.
  • 0

#4 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 14 marzo 2009 - 06:56

en el foro de juegos hay ejemplos de threads, si mal no recuerdo en la gallina...
  • 0

#5 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 11:22

¿Alguien ha probado éste código?, porque la agrego tal cual como está y no me compila y no le encuentro el problema:

http://delphi.about....l/aa081503a.htm

Saludos.
  • 0

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 marzo 2009 - 11:50

Copié el código, no me compiló. El errror que veo es "redeclared Ping". Lo que hice fue cambiar el nombre de la función por otro y compiló. Se debe a que el nombre de la función es identico a la de la unit.

Ahora bien... hice una prueba con la IP que muestra de ejemplo y no veo el cartelito... ¿será que la IP de delphi about ya no es esa? *-) 8-) ^o|

Saludos,

  • 0

#7 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 11:57

Pues al parecer no, ¿probaste con otra IP?, hice el cambio y no me compila o es que estoy haciendo algo mal:

[Pascal Error] Main.pas(1): Unable to invoke Code Completion due to errors in source code


Saludos.
  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 marzo 2009 - 12:04

Pues no te sabrí­a decir Fernando, los error que me aparecí­a a mi eran estos:


delphi
  1. [Error] Ping.pas(39): Identifier redeclared: 'Ping'
  2. [Error] Ping.pas(112): Identifier redeclared: 'Ping'
  3. [Error] Ping.pas(39): Unsatisfied forward or external declaration: '.1'
  4. [Fatal Error] Unit1.pas(7): Could not compile used unit 'Ping.pas'



Y lo que tuve que hacer fue reemplazar el nombre de la función Ping por otro... digamos IfPing. Luego para llamar a la función lo único que hice es esto:



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. const ADP_IP = '208.185.127.40'; (* http://delphi.about.com *)
  3. begin
  4. If  ifPing(ADP_IP) then
  5.   ShowMessage('About Delphi Programming reachable!');
  6. end;



Y por lo que estuve viendo en Who is, la IP de delphi.about es esa... No me muestra el cartelito...

Saludos,
  • 0

#9 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 12:40

Esos errores eran los que me salí­an e hice el cambio de nombre en la función y aún así­ no me compila. :(, Bueno seguiré buscando, traté de hacer con los Threads con una ayudita de Eduardo, entendí­ un poco la teorí­a pero en la práctica nada me comió.

Saludos.
  • 0

#10 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 marzo 2009 - 12:44

Esruve probando haciendo ping a otras IP amigo, y funciona,... a veces.

Saludos,
  • 0

#11 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 12:45

Esruve probando haciendo ping a otras IP amigo, y funciona,... a veces.

Saludos,


Ah pues, eso indica que deberé seguir buscando... :(
  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 marzo 2009 - 12:54

¿A ti, a pesar de que se congela... te funciona el código original, con el componente TIdIcmpClient?

Yo al igual que Domingo creo que el tema pasa por emplear hilos. Yo mucho del manejo de hilos no tengo idea, sólo cierta teorí­a: se declara un descendiente de la clase TThread, se sobrescribe el método Execute y en él se implementan las rutinas necesarias (en este caso el ping). Luego se instancian algunos objetos de esta clase y se mandan a ejecutar.

Saludos,
  • 0

#13 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 15 marzo 2009 - 01:01

A lo mejor se puede aprovechar el utilitario que Javier nos acercó hace unos dí­as ;). Este hace uso de unas apis y va haciendo ping al servidor de delphiaccess. Este funciona de mil maravillas.

A lo mejor podemos estudiarlo y ver el modo de adaptarlo a lo que necesitas... y te evitas usar un componente ;).

Saludos,
  • 0

#14 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 01:05

¿A ti, a pesar de que se congela... te funciona el código original, con el componente TIdIcmpClient?

Yo al igual que Domingo creo que el tema pasa por emplear hilos. Yo mucho del manejo de hilos no tengo idea, sólo cierta teorí­a: se declara un descendiente de la clase TThread, se sobrescribe el método Execute y en él se implementan las rutinas necesarias (en este caso el ping). Luego se instancian algunos objetos de esta clase y se mandan a ejecutar.

Saludos,


El código original funciona perfectamente, el problema es que si hay muchos relojes fuera de servicio se congela por minutos hasta que termine y repite el proceso.

Saludos.
  • 0

#15 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 02:40

Bueno, Tratando con Hilos, hice lo siguiente:



delphi
  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
  8.   IdIcmpClient;
  9.  
  10. type
  11.   TThreadPing = class(TThread)
  12.     private
  13.       Respuesta: String; //resultado
  14.     protected
  15.       procedure Execute; override;
  16.     public
  17.       constructor Create(IP: String);
  18.     end;
  19.  
  20.   TForm1 = class(TForm)
  21.     Button1: TButton;
  22.     pE01: TIdIcmpClient;
  23.     procedure IdIcmpClient1Reply(ASender: TComponent;
  24.       const AReplyStatus: TReplyStatus);
  25.     procedure Button1Click(Sender: TObject);
  26.   private
  27.     { Private declarations }
  28.   public
  29.     { Public declarations }
  30.   end;
  31.  
  32. var
  33.   Form1: TForm1;
  34.   cIP: String;
  35.  
  36. implementation
  37.  
  38. {$R *.dfm}
  39.  
  40. constructor TThreadPing.Create(IP: String);
  41. begin
  42. cIP := IP; //guarda la IP en una variable privada
  43. inherited Create(True);
  44. end;
  45.  
  46. procedure SetReloj(Host: String; S: TLabel; Recibe: TIdIcmpClient);
  47. begin
  48.   Recibe.Host := cIP;
  49.   with Recibe.ReplyStatus do begin
  50.   case ReplyStatusType of
  51.     rsEcho:    begin  S.Caption := 'Conectado';
  52.                         S.Font.Color := clBlue;
  53.                 end;
  54.     rsTimeOut: begin  S.Caption := 'Apagado';
  55.                         S.Font.Color := clRed;
  56.                 end;
  57.     rsErrorUnreachable: begin  S.Caption := 'Sin Conección';
  58.                         S.Font.Color := clRed;
  59.                 end;
  60.     end;
  61.   end;
  62. end;
  63.  
  64. procedure TThreadPing.Execute;
  65. begin
  66.   Synchronize(SetReloj);
  67. end;
  68.  
  69. procedure TForm1.Button1Click(Sender: TObject);
  70. var
  71.   DIR: TThreadPing;
  72. begin
  73. DIR.Create('127.0.0.1');
  74. end;
  75.  
  76. end.



No logro echarlo a andar, se queda en el Execute con "[Error] Main.pas(66): There is no overloaded version of 'Synchronize' that can be called with these arguments", estoy seguro que está totalmente mal :p, ¿una mano? :$

Saludos.
  • 0

#16 eduarcol

eduarcol

    Advanced Member

  • Administrador
  • 4.483 mensajes
  • LocationVenezuela

Escrito 15 marzo 2009 - 04:05



delphi
  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7. Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
  8. IdIcmpClient;
  9.  
  10. type
  11. TThreadPing = class(TThread)
  12.   private
  13.     Respuesta: String; //resultado
  14.     procedure SetReloj(Host: String; S: TLabel; Recibe: TIdIcmpClient);
  15.   protected
  16.     procedure Execute; override;
  17.   public
  18.     constructor Create(IP: String);
  19.   end;
  20.  
  21. TForm1 = class(TForm)
  22.   Button1: TButton;
  23.   pE01: TIdIcmpClient;
  24.   procedure IdIcmpClient1Reply(ASender: TComponent;
  25.     const AReplyStatus: TReplyStatus);
  26.   procedure Button1Click(Sender: TObject);
  27. private
  28.   { Private declarations }
  29. public
  30.   { Public declarations }
  31. end;
  32.  
  33. var
  34. Form1: TForm1;
  35. cIP: String;
  36.  
  37. implementation
  38.  
  39. {$R *.dfm}
  40.  
  41. constructor TThreadPing.Create(IP: String);
  42. begin
  43. cIP := IP; //guarda la IP en una variable privada
  44. inherited Create(True);
  45. end;
  46.  
  47. procedure TThreadPing.SetReloj(Host: String; S: TLabel; Recibe: TIdIcmpClient);
  48. begin
  49. Recibe.Host := cIP;
  50. with Recibe.ReplyStatus do begin
  51. case ReplyStatusType of
  52.     rsEcho:    begin  S.Caption := 'Conectado';
  53.                       S.Font.Color := clBlue;
  54.                 end;
  55.     rsTimeOut: begin  S.Caption := 'Apagado';
  56.                       S.Font.Color := clRed;
  57.                 end;
  58.   rsErrorUnreachable: begin  S.Caption := 'Sin Conección';
  59.                       S.Font.Color := clRed;
  60.                 end;
  61.   end;
  62. end;
  63. end;
  64.  
  65. procedure TThreadPing.Execute;
  66. begin
  67. Synchronize(SetReloj);
  68. end;
  69.  
  70. procedure TForm1.Button1Click(Sender: TObject);
  71. var
  72. DIR: TThreadPing;
  73. begin
  74. DIR.Create('127.0.0.1');
  75. end;
  76.  
  77. end.



Debes meter el procedure SetReloj dentro del TThread, ya que Syncronize trabaja con TThreadMetod
  • 0

#17 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 04:14

Hola Eduardo, gracias por la aclaración, pero aún persiste el problema y tiene que ver con el procedimiento, :s
  • 0

#18 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 15 marzo 2009 - 06:49

Hola compañeros, con la ayuda de eduardo pude hacer un Thread, pero el resultado sigue siendo el mismo, dejo el .pas para que lo vean.

Saludos.
  • 0

#19 Kipow

Kipow

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 228 mensajes
  • LocationGuatemala

Escrito 16 marzo 2009 - 06:14

Yo no tengo mucha experiencia con Threads pero si he hecho uso de ellos en un par de aplicaciones ultimamente. y te pudo decir esto.

1. El metodo syncronize recibe un procedimiento sin parametros es por eso lo de tu error.
2. Te sugiero crear dentro del thread el Componente de las Indy.
3.

delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3. DIR: TThreadPing;
  4. begin
  5. DIR.Create('127.0.0.1');
  6. DiR.Resume; // Con esto le indicas que inicie el thread. porque el parametro true del constructor lo inicia pausado.
  7. end;


Saludos.

  • 0

#20 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 16 marzo 2009 - 07:01

Yo no tengo mucha experiencia con Threads pero si he hecho uso de ellos en un par de aplicaciones ultimamente. y te pudo decir esto.

1. El metodo syncronize recibe un procedimiento sin parametros es por eso lo de tu error.
2. Te sugiero crear dentro del thread el Componente de las Indy.
3.

delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3. DIR: TThreadPing;
  4. begin
  5. DIR.Create('127.0.0.1');
  6. DiR.Resume; // Con esto le indicas que inicie el thread. porque el parametro true del constructor lo inicia pausado.
  7. end;


Saludos.


Se me fue adelante Kipow, es correcta la indicación, no debes pasar un método con parámetros a Syncronize.



delphi
  1. type TThreadMethod = procedure of object;


  • 0




IP.Board spam blocked by CleanTalk.