C# 多线程 ping
Posted
技术标签:
【中文标题】C# 多线程 ping【英文标题】:C# multi-thread ping 【发布时间】:2011-03-07 11:04:06 【问题描述】:我正在开发一个网络监控应用程序,它会 ping 一个(未知)数量的主机。到目前为止,我有下面的代码。我已经用函数zping
创建了一个类PingHost
,并且我在计时器的帮助下每2 秒调用一次,以让2 个ping 完成,即使其中一个得到TimedOut
。但我认为更好的解决方案是为每个 ping 生成一个新线程,以便每个主机的 ping 都是独立的。
谁能给我一个提示如何做到这一点?
namespace pinguin
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void timer1_Tick(object sender, EventArgs e)
PingHost caca = new PingHost();
PingHost caca1 = new PingHost();
this.label1.Text = caca.zping("89.115.14.160");
this.label2.Text = caca1.zping("89.115.14.129");
public class PingHost
public string zping(string dest)
Application.DoEvents();
Ping sender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 50;
int failed = 0;
int pingAmount = 5;
string stat = "";
PingReply reply = sender.Send(dest, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
stat = "ok";
else
stat = "not ok!";
return stat;
【问题讨论】:
这似乎适合Code Review。 你可能想看看这个以前的问题和答案 - ***.com/questions/4886691/… 为什么不从这里开始:msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx 【参考方案1】:如果您使用 .NET 4,则可以使用 Parallel.Invoke
。
【讨论】:
【参考方案2】:您可以处理Ping.PingCompleted
事件:
ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);
然后使用:
ping.SendAsync()
旁注:为您的类和例程选择更合适的名称。 PingHost 更适合作为例程名称
【讨论】:
【参考方案3】:一旦我写了这样一个解决方案(它不断 ping 大约 300 台机器):
public class ManyAdressPing
private readonly bool bAutoStarted;
private readonly CancellationTokenSource cancel = new CancellationTokenSource();
public ConcurrentDictionary<IPAddress, OneAddressPing> pingi = new ConcurrentDictionary<IPAddress, OneAddressPing>();
public ManyAdressPing(bool AutoStarted = true)
bAutoStarted = AutoStarted;
public int CountPings => pingi.Count;
public void AddPingAddress(IPAddress addr, int msTimeOut = 3000, int BetweenPing = 3000)
var oap = new OneAddressPing(addr, cancel.Token, msTimeOut, BetweenPing);
if (bAutoStarted) oap.Start();
pingi.TryAdd(oap.ipAddress, oap);
public void RemovePingAddress(IPAddress addr)
if (pingi.TryRemove(addr, out var p)) p.Stop();
public void Stop()
cancel.Cancel();
foreach (var pair in pingi) pair.Value.Stop();
public PingReply GetReply(IPAddress addr)
if (pingi.ContainsKey(addr)) return pingi[addr].GetReply();
return null;
public Tuple<long, long> GetSuccessOperation(IPAddress addr)
if (pingi.ContainsKey(addr)) return pingi[addr].GetSuccessOperation();
return null;
public PingReply[] GetReply()
PingReply[] ret = pingi.Values.Select(x=>x.GetReply()).ToArray();
return ret;
public PingInfo GetPingInfo(IPAddress addr)
if (pingi.ContainsKey(addr))
var ret = new PingInfo();
var p = pingi[addr];
ret.reply = p.GetReply();
ret.SuccessPing = p._SuccessReply;
ret.FailPing = p._FailReply;
ret.LastSuccessPing = p.LastSuccessfullPing;
return ret;
return null;
public bool IsPinged(IPAddress addr)
if (pingi.ContainsKey(addr)) return true;
return false;
public IPAddress[] GetAddressesPing()
return pingi.Keys.ToArray();
public class PingInfo
public PingReply reply;
public long SuccessPing = 0;
public long FailPing = 0;
public DateTime LastSuccessPing;
public override string ToString()
return $"Sping: SuccessPing last=LastSuccessPing, Fping:FailPing, reply:reply";
public class OneAddressPing
public static byte[] bu =
0
;
public long _FailReply;
public long _SuccessReply;
private bool bStop = false;
private readonly CancellationToken cancellationToken;
public DateTime LastSuccessfullPing = DateTime.MinValue;
public int mSecBetweenPing = 3000;
public Ping ping;
public PingOptions popt;
private Task pTask;
// Here is a self-written LIFO stack
public LightQueue<PingReply> replys = new LightQueue<PingReply>(10);
private readonly AutoResetEvent reset = new AutoResetEvent(false);
private Logger log = null;
private Task pinging = null;
public OneAddressPing(IPAddress addr, CancellationToken ct, int timeOut = 3000, int BetweenPing = 3000, Logger _log =null)
ipAddress = addr;
popt = new PingOptions();
popt.DontFragment = false;
cancellationToken = ct;
mSecTimeOut = timeOut;
mSecBetweenPing = BetweenPing;
log = _log;
public int mSecTimeOut get; set; = 3000;
public IPAddress ipAddress get; set;
public int CountPings => replys.Length;
private void SetReply(PingReply rep)
if (rep == null) return;
replys.Put(rep);
if (rep.Status == IPStatus.Success)
Interlocked.Increment(ref _SuccessReply);
LastSuccessfullPing = DateTime.Now;
else
Interlocked.Increment(ref _FailReply);
public async Task Start()
if (pTask == null || pTask.Status != TaskStatus.Running)
ping = new Ping();
Task.Factory.StartNew(PingCircle, TaskCreationOptions.RunContinuationsAsynchronously | TaskCreationOptions.LongRunning); pTask = Task.Run(PingCircle, cancellationToken);
public void Stop()
if (pTask.Status == TaskStatus.Running)
bStop = true;
try
pTask.Wait(mSecTimeOut, cancellationToken);
catch (Exception ex)
log.ErrorSource($"Error ping stop: ex.Message");
private async Task PingCircle()
while (cancellationToken.IsCancellationRequested == false && !bStop)
try
try
PingReply rep = await ping.SendPingAsync(ipAddress, mSecTimeOut, bu,popt);
if (rep != null) SetReply(rep);
catch (PingException p)
// ignore ping error
Debug.WriteLine($"error: p");
catch (Exception ee)
log?.ErrorSource(ee);
Debug.WriteLine($"error: ee");
await Task.Delay(mSecBetweenPing, cancellationToken);
catch (Exception ee)
log?.ErrorSource(ee);
public PingReply GetReply()
if (replys.IsEmpty) return null;
return replys.PeekLast(0);
public Tuple<long, long> GetSuccessOperation()
return new Tuple<long, long>(_SuccessReply, _FailReply);
public bool LongPingSuccess()
int ret = 0;
for (int i = 0; i < 5; i++)
var r = replys.PeekLast(i);
if (r.Status == IPStatus.Success) ret++;
if (ret > 2) return true;
return false;
【讨论】:
以上是关于C# 多线程 ping的主要内容,如果未能解决你的问题,请参考以下文章