我正在开发一个网络监控应用程序,用于ping(未知)数量的主机。到目前为止,我有以下代码。我创建了一个带有函数PingHost
的类zping
,我每隔2秒就用一个计时器调用它,让2个ping完成,即使其中一个得到{{1} }}。但我认为更好的解决方案是为每个ping生成一个新线程,这样每个主机的ping都是独立的。
任何人都可以给我一个如何做到这一点的提示吗?
TimedOut
答案 0 :(得分:2)
如果您使用.NET 4,则可以使用Parallel.Invoke
。
答案 1 :(得分:2)
您可以处理Ping.PingCompleted
事件:
ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);
然后使用:
ping.SendAsync()
旁注:为您的类和例程选择更合适的名称。 PingHost更适合作为例程名称
答案 2 :(得分:0)
一旦我编写了这样的解决方案(它会不断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;
}
}