Einzelnen Beitrag anzeigen

berens

Registriert seit: 3. Sep 2004
434 Beiträge
 
Delphi 10.4 Sydney
 
#1

idICMP nicht (Multithread+MultiInstanz) fähig?

  Alt 11. Jan 2008, 16:22
Hi!
Ich habe eine Liste mit IP Adressen die ich der Reihe nach anpingen möchte. Die IPs gehören alle _einem_ PC. Jeder PC wird durch ein TFoo Objekt repräsentiert. Deswegen wird FAlive auch auf True gesetzt, sobald eine einzige IP Antwort gibt.

Problem: Ich erhalte bei einer zufälligen Instanz von TFoo das PingReply Ereignis für ein anderes Objekt. Also bekommt das Objekt mit der IP 192.168.0.2 in seiner IP Liste auf einmal das PingErgebnis für die 192.168.0.3 (als Beispiel) und anders herum (obwohl er nicht diese IP Adresse hat!). Das ist natürlich blöd und darf nicht sein.

Frage: Wie Pinge ich mehrere Hosts (max. 10 Stück) möglichst schnell/gleichzeitig ohne den MainThread aufzuhalten? Soll ich nur eine Instanz von TidIcmp nehmen und dann alle IPs nacheinander abarbeiten und dann den Instanzen von TFoo "per Hand" die (Nicht-)Erfolgsmeldung zukommen lassen?

Bedenke dass ein PC eine Verzögerung von 2 Sekunden haben kann, bis er antwortet. Bei 10 PCs (die angenommen alle aus sind) dauert das schon 20 Sekunden. Ich würde die Ansicht aber gerne alle 5-10 Sekunden aktualisieren lassen.

Für Antworten wie immer sehr dankbar.

Delphi-Quellcode:
procedure TFoo.Ping;
var
  j: integer;
  PingThread: THAL2_PC_State_Ping_Thread;
begin
  FPingThreadsRunning := 0;
  FintIPsReplying := 0;

  for j := 0 to IP.Count - 1 do begin
    inc(FPingThreadsRunning);
    PingThread := Tmeinthread.Create(True);
    with PingThread do begin
      Host := IP.Strings[j]; // IP ist eine TStringList mit den IP Adressen
      Callback_Object := Self;
      FreeOnTerminate := True;
      Resume;
    end;
  end;
end;

procedure Tmeinthread.Execute;
var
  idICMP: TIdIcmpClient;
begin
  idICMP := TIdIcmpClient.Create(NIL);
  try
    idICMP.ReceiveTimeout := 2000;
    if assigned(Callback_Object) then begin
      idICMP.OnReply := Callback_Object.PingReply;
    end;
    idICMP.Host := Self.Host; // <-- Self.Host ist die IP Adresse
    idICMP.Ping;
  finally
    FreeAndNil(idICMP);
  end;
end;

procedure TFoo.PingReply(ASender: TComponent; const AReplyStatus: TReplyStatus);
begin
  if AReplyStatus.ReplyStatusType <> rsTimeOut then begin
// if (IP.IndexOf(AReplyStatus.FromIPAddress) > -1) then begin
    inc(FintIPsReplying);
    FAlive := True;
// end;
  end;
  dec(FPingThreadsRunning);

  if (FPingThreadsRunning < 1) then begin
    if (FintIPsReplying > 0) then begin
      // Hole weitere Infos
    end else begin
      // Der Host ist ausgeschaltet oder nicht erreichbar!
      FAlive := False;
    end;
  end;
end;
  Mit Zitat antworten Zitat