【问题标题】:C# multi-thread pingC# 多线程 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;
        }
    }
}

【问题讨论】:

标签: c# multithreading ping


【解决方案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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2012-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-11
        • 1970-01-01
        • 2011-10-05
        • 2011-01-08
        • 1970-01-01
        相关资源
        最近更新 更多