title: Delphi (XE2) Indy (10) Multithread Ping
body: <p>I have a room with 60 computers/devices (40 computers and 20 oscilloscopes Windows CE based) and I would like to know which and every one is alive using ping. First I wrote a standard ping (see here <a href="https://stackoverflow.com/questions/12723081/delphi-indy-ping-error-10040">Delphi Indy Ping Error 10040</a>), which is working fine now but takes ages when most computers are offline.</p>
  
  <p>So what I am trying to do is to write a MultiThread Ping but I am quite struggling with it. I have seen only very few examples over the internet and no one was matching my needs, that's why I try to write it myself.</p>
  
  <p>I use XE2 and Indy 10 and the form is only constitued of a memo and a button.</p>
  
  <pre><code>unit Main;
  
  interface
  
  uses
    Winapi.Windows, System.SysUtils, System.Classes, Vcl.Forms,
    IdIcmpClient, IdGlobal, Vcl.StdCtrls, Vcl.Controls;
  
  type
    TMainForm = class(TForm)
      Memo1: TMemo;
      ButtonStartPing: TButton;
      procedure ButtonStartPingClick(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
    end;
  
  type
    TMyPingThread = class(TThread)
    private
      fIndex : integer;
      fIdIcmpClient: TIdIcmpClient;
      procedure doOnPingReply;
    protected
      procedure Execute; override;
    public
      constructor Create(index: integer);
    end;
  
  var
    MainForm: TMainForm;
    ThreadCOunt : integer;
  
  implementation
  
  {$R *.dfm}
  
  constructor TMyPingThread.Create(index: integer);
  begin
    inherited Create(false);
  
    fIndex := index;
    fIdIcmpClient := TIdIcmpClient.Create(nil);
    fIdIcmpClient.ReceiveTimeout := 200;
    fIdIcmpClient.PacketSize := 24;
    fIdIcmpClient.Protocol := 1;
    fIdIcmpClient.IPVersion := Id_IPv4;
  
    //first computer is at adresse 211
    fIdIcmpClient.Host := '128.178.26.'+inttostr(211+index-1);
  
    self.FreeOnTerminate := true;
  end;
  
  procedure TMyPingThread.doOnPingReply;
  begin
    MainForm.Memo1.lines.add(inttostr(findex)+' '+fIdIcmpClient.ReplyStatus.Msg);
    dec(ThreadCount);
  
    if ThreadCount = 0 then
      MainForm.Memo1.lines.add('--- End ---');
  end;
  
  procedure TMyPingThread.Execute;
  begin
    inherited;
  
    try
      fIdIcmpClient.Ping('',findex);
    except
    end;
  
    while not Terminated do
    begin
      if fIdIcmpClient.ReplyStatus.SequenceId = findex then Terminate;
    end;
  
    Synchronize(doOnPingReply);
    fIdIcmpClient.Free;
  end;
  
  procedure TMainForm.ButtonStartPingClick(Sender: TObject);
  var
    i: integer;
    myPing : TMyPingThread;
  begin
    Memo1.Lines.Clear;
  
    ThreadCount := 0;
    for i := 1 to 40 do
    begin
      inc(ThreadCount);
      myPing := TMyPingThread.Create(i);
      //sleep(10);
    end;
  end;
  
  end.
  </code></pre>
  
  <p>My problem is that it "seems" to work when I uncomment the "sleep(10)", and "seems" not to be working without it. This for sure means I am missing a point in the threading I have written.</p>
  
  <p>In other words. When Sleep(10) is in the code. Every time I clicked the button to get to check the connections the result was correct.</p>
  
  <p>Without the sleep(10), it is working "most" of the time but some times the result is wrong giving me a ping echo on offline computers and no ping echo on online computer, as is the ping reply was not assigned to the correct thread.</p>
  
  <p>Any comment or help is welcome.</p>
  
  <p><strong>----- EDIT / IMPORTANT -----</strong></p>
  
  <p>As a general follow up of this question, @Darian Miller started a <a href="https://code.google.com/p/delphi-stackoverflow/" rel="nofollow noreferrer" title="Google Code Project">Google Code project here</a>  <a href="https://code.google.com/p/delphi-stackoverflow/" rel="nofollow noreferrer">https://code.google.com/p/delphi-stackoverflow/</a> which is a working basis. I mark his answer as the "accepted answer" but users should refer to this open source project (all the credit belongs to him) as it will surely be extended and updated in the future.</p>