Unterschiedliche Adressen "gleichzeitig" anpingen

#1
Hallo zusammen,

ich habe versucht ein Programm zu schreiben, was mehrere Adressen gleichzeitig anpingen kann.
Leider habe ich noch Probleme mit dem Asynchronen senden des Pings.
Mein "geklauter" Code sieht jetzt so aus:

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Ping_WinForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        AutoResetEvent waiter = new AutoResetEvent(false);
     

        private void cmdStart_Click(object sender, EventArgs e)
        {
            string [] ip;
            int i = 0;
            Ping pingSender = new Ping();

            // Sobald das PingCompleted Ereignis ausgelöst wird,
            // wird die Methode PingCompletedCallback aufgerufen.
            pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);

            // Erzeuge einen Puffer mit der Länge von 32 Bytes
            // die versendet werden sollen.
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);

            int timeout = 12000;

            PingOptions options = new PingOptions(64, true);

            ip = txtPingIp.Text.Split(';');

            do
            {
                foreach (string s in ip)
                {
                    pingSender.SendAsync(s, timeout, buffer, options, waiter);
                    waiter.WaitOne(1000);
                }

                if (!chkEver.Checked)
                    i++;

            } while (i < 1);

        }

        private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
        {
            // Falls die Operation beendet wurde, zeige dem Benutzer eine Nachricht.
            if (e.Cancelled)
            {
                lblInfo.Text += " ping beendet\n";

                // Lasse den main Thread weiterlaufen. UserToken ist
                // das AutoResetEvent Objekt auf das der main Thread wartet.
                ((AutoResetEvent) e.UserState).Set();
            }

            // Falls ein Fehler aufgetreten ist, zeige die Ausnahme an.
            if (e.Error != null)
            {
                lblInfo.Text += " Ping failed:";
             
                lblInfo.Text += (e.Error.ToString() + "\n");

                // Lasse den main Thread weiterlaufen.
                ((AutoResetEvent) e.UserState).Set();
            }

            PingReply reply = e.Reply;

            DisplayReply(reply);

            // Lasse den main Thread weiterlaufen.
            ((AutoResetEvent) e.UserState).Set();
        }



        private void DisplayReply(PingReply reply)
        {
            if (reply == null)
                return;

            lblInfo.Text += " ping status " + reply.Status;
            if (reply.Status == IPStatus.Success)
            {
                lstOutput.Items.Add("Address: " + reply.Address.ToString());
                lstOutput.Items.Add("RoundTrip time: "+ reply.RoundtripTime);
                lstOutput.Items.Add("Time to live: "+ reply.Options.Ttl + " ms");
                lstOutput.Items.Add("Don't fragment: "+ reply.Options.DontFragment);
                lstOutput.Items.Add("Buffer size: "+ reply.Buffer.Length);
            }
        }
    }
}
Mein Problem ist jetzt, wenn ich das ganze in einer Endlosschleife laufen lasse, blockiert die Form und ich kann das Pingen natürlich auch nicht mehr beenden. Z.B. mit einem Klick.
Wenn jemand verbesserungsvorschläge zu dem hier hat, wäre ich natürlich auch dankbar!
C#:
  do
            {
                foreach (string s in ip)
                {
                    pingSender.SendAsync(s, timeout, buffer, options, waiter);
                    waiter.WaitOne(1000);
                }

                if (!chkEver.Checked)
                    i++;

            } while (i < 1);
Danke euch! :)


Edit: Übrigens ist die Endlosschleife für die Analyse gedacht und das Protokolliere ich in einer Textdatei.
 
Zuletzt bearbeitet:
#2
Moin Moin,

also ich persönlich arbeite bei soetwas gern mit Delegaten, ist recht simpel wenn man das Prinzip einmal verstanden hat.

C#:
public class MeineAsynchroneKlasse
{
   private delegate void Handler_für_Endlosschleife();
  private static bool IstSchleifeAktiv = false;
  public void Endlosschleife_Beginnen()
  {
  IstSchleifeAktiv = true;
  Handler_für_Endlosschleife Handler =
  new Handler_für_Endlosschleife(this.Schleife_Abarbeiten);
  Handler.BeginInvoke(new AsyncCallback(this.Schleife_Zu_Ende), Handler);
  }
 
   private void Schleife_Abarbeiten()
  {
  while(IstSchleifeAktiv)
  {
  // Etwas tun
  System.Threading.Thread.CurrentThread.Join(100);
  }
  }
  private void Schleife_Zu_Ende(IAsyncResult ar)
  {
  (ar.AsyncState as Handler_für_Endlosschleife).EndInvoke(ar);
  }
  public void Endlosschleife_Beenden()
  {
  IstSchleifeAktiv = false;
  }
}
Wenn du aus der Schleife einen Wert mit bspw. einem Event rausgibst und in der Form verwenden willst, solltest du dir die System.Windows.Forms.Control.InvokeRequired Eigenschaft etwas genauer ansehen ;)
 
#3
Danke für deine Hilfe. Ich habe das ganze jetzt in einem eigenen Thread realisiert. Hätte aber noch eine verständnisfrage zur asynchronen Programmierung:

Wird durch asynch Programmrierung die Form ebenfalls geblockt?

Ich habe das jetzt so verstanden:

C#:
{
//CODE

//Ich rufe hier meine asynch methode auf

//hier wird der code weiter ausgeführt obwohl meine asynch
//methode noch läuft
}

asynch methode
{
//CODE
}
Hier würde dann einfach meine Mehtode weiterlaufen und nicht warten bis der asynch Mehtodenaufruf abgeschlossen ist um nicht darauf warten zu müssen, aber die Form würde trotzdem Blockieren.

Oder habe ich das falsch verstanden?
 
Oben