void pinger_PingCompleted(object sender, PingCompletedEventArgs e) { try { object[] args = (object[])e.UserState; DateTime time = (DateTime)args[0]; long pingNum = (long)args[1]; PingGraphControl graph = (PingGraphControl)args[2]; int pingTargetId = (int)args[3]; // Do not assume the pingTargets or pingGraphs containers will have this key! IPAddress remoteHost = (IPAddress)args[4]; Ping pinger = (Ping)args[5]; pinger.PingCompleted -= pinger_PingCompleted; PingInstancePool.Recycle(pinger); if (e.Cancelled) { graph.AddPingLogToSpecificOffset(pingNum, new PingLog(time, 0, IPStatus.Unknown)); Interlocked.Increment(ref failedPings); return; } graph.AddPingLogToSpecificOffset(pingNum, new PingLog(time, (short)e.Reply.RoundtripTime, e.Reply.Status)); if (e.Reply.Status != IPStatus.Success) { Interlocked.Increment(ref failedPings); if (clearedDeadHosts && pingTargets.ContainsKey(pingTargetId)) { CreateLogEntry("" + time.ToString(dateFormatString) + ", " + remoteHost.ToString() + ": " + e.Reply.Status.ToString()); } } else { if (!clearedDeadHosts) { pingTargetHasAtLeastOneSuccess[pingTargetId] = true; } Interlocked.Increment(ref successfulPings); } } finally { UpdatePingCounts(Interlocked.Read(ref successfulPings), Interlocked.Read(ref failedPings)); } }
private void controllerLoop(object arg) { currentIPAddress = null; object[] args = (object[])arg; string host = (string)args[0]; bool traceRoute = (bool)args[1]; bool reverseDnsLookup = (bool)args[2]; foreach (PingGraphControl graph in pingGraphs.Values) { graph.ClearAll(); graph.MouseDown -= panel_Graphs_MouseDown; graph.MouseMove -= panel_Graphs_MouseMove; graph.MouseLeave -= panel_Graphs_MouseLeave; graph.MouseUp -= panel_Graphs_MouseUp; } Interlocked.Exchange(ref successfulPings, 0); Interlocked.Exchange(ref failedPings, 0); pingGraphs.Clear(); pingTargets.Clear(); pingTargetHasAtLeastOneSuccess.Clear(); clearedDeadHosts = false; panel_Graphs.Invoke((Action)(() => { panel_Graphs.Controls.Clear(); })); graphSortingCounter = 0; IPAddress target = null; try { string[] addresses = host.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); target = StringToIp(addresses[0]); currentIPAddress = target.ToString(); CreateLogEntry("(" + DateTime.Now.ToString(dateFormatString) + "): Initializing pings to " + host); // Multiple addresses if (addresses.Length > 1) { // Don't clear dead hosts from a predefined list clearedDeadHosts = true; foreach (string address in addresses) { IPAddress ip = StringToIp(address.Trim()); string hostName = reverseDnsLookup ? GetIpHostname(ip) : ""; AddPingTarget(ip, hostName); } } // Route else if (traceRoute) { CreateLogEntry("Tracing route ..."); foreach (TracertEntry entry in Tracert.Trace(target, 64, 5000, reverseDnsLookup)) { CreateLogEntry(entry.ToString()); AddPingTarget(entry.Address, entry.Hostname); } } // Single address else { AddPingTarget(target, host); } CreateLogEntry("Now beginning pings"); DateTime lastPingAt = DateTime.Now.AddSeconds(-60); byte[] buffer = new byte[0]; long numberOfPingLoopIterations = 0; DateTime tenPingsAt = DateTime.MinValue; while (true) { try { if (!clearedDeadHosts && tenPingsAt != DateTime.MinValue && tenPingsAt.AddSeconds(10) < DateTime.Now) { if (pingTargets.Count > 1) { IList <int> pingTargetIds = pingTargets.Keys; foreach (int pingTargetId in pingTargetIds) { if (!pingTargetHasAtLeastOneSuccess[pingTargetId]) { // This ping target has not yet had a successful response. Assume it never will, and delete it. panel_Graphs.Invoke((Action)(() => { pingTargets.Remove(pingTargetId); panel_Graphs.Controls.Remove(pingGraphs[pingTargetId]); pingGraphs[pingTargetId].MouseDown -= panel_Graphs_MouseDown; pingGraphs[pingTargetId].MouseMove -= panel_Graphs_MouseMove; pingGraphs[pingTargetId].MouseLeave -= panel_Graphs_MouseLeave; pingGraphs[pingTargetId].MouseUp -= panel_Graphs_MouseUp; pingGraphs.Remove(pingTargetId); if (pingGraphs.Count == 0) { Label lblNoGraphsRemain = new Label(); lblNoGraphsRemain.Text = "All graphs were removed because" + Environment.NewLine + "none of the hosts responded to pings."; panel_Graphs.Controls.Add(lblNoGraphsRemain); } else { pingGraphs[pingGraphs.Count - 1].ShowTimestamps = true; // In case the graph we just removed was the last graph, which is supposed to show the timestamps along its bottom, this will make sure the new (or old) bottom is showing timestamps. } })); } } panel_Graphs.Invoke((Action)(() => { panel_Graphs_Resize(null, null); })); } clearedDeadHosts = true; } while (pingDelay <= 0) { Thread.Sleep(100); } int msToWait = (int)(lastPingAt.AddMilliseconds(pingDelay) - DateTime.Now).TotalMilliseconds; while (msToWait > 0) { Thread.Sleep(Math.Min(msToWait, 1000)); msToWait = (int)(lastPingAt.AddMilliseconds(pingDelay) - DateTime.Now).TotalMilliseconds; } lastPingAt = DateTime.Now; // We can't re-use the same Ping instance because it is only capable of one ping at a time. foreach (var targetMapping in pingTargets) { PingGraphControl graph = pingGraphs[targetMapping.Key]; long offset = graph.ClearNextOffset(); Ping pinger = PingInstancePool.Get(); pinger.PingCompleted += pinger_PingCompleted; pinger.SendAsync(targetMapping.Value, 5000, buffer, new object[] { lastPingAt, offset, graph, targetMapping.Key, targetMapping.Value, pinger }); } } catch (ThreadAbortException ex) { throw ex; } catch (Exception) { } numberOfPingLoopIterations++; if (numberOfPingLoopIterations == 10) { tenPingsAt = DateTime.Now; } } } catch (ThreadAbortException) { } catch (Exception ex) { if (!(ex.InnerException is ThreadAbortException)) { MessageBox.Show(ex.ToString()); } } finally { CreateLogEntry("(" + DateTime.Now.ToString(dateFormatString) + "): Shutting down pings to " + host); if (isRunning) { btnStart_Click(btnStart, new EventArgs()); } } }