Asynchrone Ping
Lief in ein komisches "problem". Eine Anwendung, die pingsweeps ganze Netzwerke. Funktioniert Super, bis Sie zum Netz mit der netmask 255.255.0.0 (die 65k + Adressen).
Sende ich Ihnen meine pings so:
foreach (string str in ListContainingAddresses)
{
using (Ping ping = new Ping())
{
if (pingCounter == 10000) { Thread.Sleep(10000); pingCounter = 0; }
//Make an eventhandler
ping.PingCompleted += new PingCompletedEventHandler(pingCompleted);
//Send the pings asynchronously
ping.SendAsync(IPAddress.Parse(str), 1000);
sentPings++;
//This counts pings being sent out
pingCounter++;
}
}
Und erhalten Sie wie folgt:
public void pingCompleted(object sender, PingCompletedEventArgs e)
{
//This counts recieved addresses
recievedIpAddresses++;
if (e.Reply.Status == IPStatus.Success)
{
//Do something
}
else
{
/*Computer is down*/
}
//This checks if sent equals recieved
if (recievedIpAddresses == sentPings )
{
//All returned
}
}
Problem ist, dass a) Manchmal (sehr selten) das es nicht komplett ist (Bedingung nicht erfüllt). b) Wenn es nicht komplett die zahlen nicht passen? Wenn ich drucken gesendet und empfangen, nur jetzt sind Sie
Sent: 65025 Recieved: 64990
Trotz das die Bedingung erfüllt ist und die Anwendung wechselt auf? Ich weiß nicht, warum und wie dies geschieht. Ist der code ausführen zu schnell für die Anwendung zu aktualisieren, zwei ints? Einige pings verloren gehen auf dem Weg? Wenn ich versuche, es auf ein Subnetz mit 255 Adressen dieses problem nie passiert.
Verwenden kann CountDownEvent anstelle von Variablen seit seiner .NET 3.5
- Mein Geld wäre auf thread-Sicherheit. Obwohl es würde die Dinge verlangsamen ein wenig, ich würde konzentrieren Sie sich auf die pingCompleted thread-safe.
- blöde Frage: warum nicht
nmap
? Ich Wette, es werden Schnellste Lösung möglich - Nicht dumm, ich will lernen, wie es selbst zu tun, so einfach ist das 🙂
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie keine Verriegelung an allen? Das sieht aus wie dein problem zu mir. Ich kann sehen, alle Arten von race-conditions und Speicher Prozessor-cache-Probleme potenziell in Ihrem code.
Versuchen Sie es mit
lock
für den Schutz derrecievedIpAddresses == sentPings
undMit
lock
Zum Beispiel:
Dem obigen Beispiel wird die Kraft, die liest und schreibt von shared-memory, so dass verschiedene CPU-Kerne nicht Lesen unterschiedliche Werte haben. Allerdings, je nach code, den Sie vielleicht brauchen viel mehr coarse-grained locking, wo die erste Schleife schützt sowohl
sentPings
undpingCounter
in einemlock
, und vielleicht sogar die zweite Methode ist komplett geschützt mit einemlock
.Können die Leute sagen, nicht zu verwenden
lock
denn es verursacht performance-Probleme und lock-free ist sehr trendy. Die bottom line istlock
ist einfacher als andere alternativen die meisten der Zeit. Möglicherweise müssen Sie Ihre sperren mehr grobkörnige, als das obige Beispiel, weil Sie potenziell race-Bedingungen als auch. Es ist schwer zu geben, eine bessere Probe, ohne zu sehen, das gesamte Programm.Interlocked.Increment
Hauptgrund für den Einsatz
lock
hier ist die Kraft, die jeder Lesen und schreiben kommen aus dem Arbeitsspeicher, nicht die CPU-cache, und daher sollten Sie konsistente Werte. Eine alternative zum sperren ist die Verwendung Verriegelt.Inkrement, aber wenn Sie diese auf zwei separate Variablen müssen Sie sorgfältig beobachten, für race conditions.Race conditions
(Edit)
Selbst wenn Sie sperren Sie möglicherweise ein problem haben. Sehen Sie diese Zeitleiste für 13-Ziel-Adressen (Pech für einige). Wenn Sie sich nicht wohl mit, warum das so ist, dann haben Sie einen Blick auf "Verwaltete Threading-Grundlagen" und "Threading in C# - Joseph Albahari"
sentPings++
sentPings++
(jetzt gleich 13)recievedIpAddresses == sentPings
test jetzt ausfällt, sind Sie nicht gleichpingCompleted
und hatrecievedIpAddresses++;
Müssen Sie sorgfältig beobachten, für diese Art von race-Bedingung in den code ein, und passen Sie es entsprechend. Das ganze über threads ist, dass Sie sich überlappen Ihre Operationen.
SyncRoot
Fußnote:
Warum ist
SyncRoot
erklärt:private readonly object SyncRoot = new object();
?static
console-app, es muss seinstatic
. Aber, wenn Siestatic
in eine Klasse, dann ist jede Instanz wird die Sperre auf das gleiche Objekt, so wird es Konfliktereadonly
zu erklären, die Absicht, und verhindern, dass Sie (oder andere Teammitglieder) überschreiben, die es späterobject
als:SyncRoot
als ein Beispiel; Visual Studio hat in der Vergangenheit nannte es in seiner snippetsInterlocked
. Coarse-grained locking kann einfacher sein.pingCompleted
Methoden gleichzeitig laufen in verschiedenen threads. Nicht, dass die Antwort auf Ihre Frage? Als für wie das wäre in deinem Programm, kann ich nicht sagen, da ich nicht weiß, was Sie tun in der Seite Ihreif
Aussagen. Potenziell Sie Ihr Programm beenden konnte, bevor 5 von Ihnen kommen zurück, oder Sie vielleicht abschließen, bevor Sie beenden, wenn auf Ihrem Haupt-thread warten Sie, bis Sie erhalten haben, so viele wie geschickt.