C# Ping.SendAsync陷入无限循环

C# Ping.SendAsync陷入无限循环,c#,networking,ping,C#,Networking,Ping,我正在尝试获取本地网络上所有主机的列表。下列的但是Ping.SendAsync()被困在无限循环中,即使我保持一个非常小的超时,例如20。这是我的密码 static CountdownEvent countdown; static int upCount = 0; static object lockObj = new object(); const bool resolveNames = false; static

我正在尝试获取本地网络上所有主机的列表。下列的但是Ping.SendAsync()被困在无限循环中,即使我保持一个非常小的超时,例如20。这是我的密码

        static CountdownEvent countdown;
        static int upCount = 0;
        static object lockObj = new object();
        const bool resolveNames = false;
        static List<string> activeInterfaces = new List<string>();

        static void p_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            try
            {

                string ip = (string)e.UserState;
                if (e.Reply != null && e.Reply.Status == IPStatus.Success)
                {
                    //if (resolveNames)
                    //{
                    //    string name;
                    //    try
                    //    {
                    //        IPHostEntry hostEntry = Dns.GetHostEntry(ip);
                    //        name = hostEntry.HostName;
                    //    }
                    //    catch (SocketException ex)
                    //    {
                    //        name = "?";
                    //    }
                    //    Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
                    //}
                    //else
                    //{
                    activeInterfaces.Add(ip);
                    Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
                    //}
                    lock (lockObj)
                    {
                        upCount++;
                    }
                }
                else if (e.Reply == null)
                {
                    Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
                }
                countdown.Signal();
            }
            catch (Exception exp)
            {
                Console.WriteLine("Here you go...");
            }

        }


        [HttpGet]
        [Route("api/pc/getOnlinePCs")]
        public List<string> GetOnlinePCs()
        {

            activeInterfaces.Clear();
            //List<string> activeInterfaces=new List<string>();
            string ipBase = "";

            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                if (ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    ipBase = ip.ToString().Substring(0, (ip.ToString().LastIndexOf(".") + 1));//"10.22.4.";

                }
            }


            countdown = new CountdownEvent(1);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 2; i < 254; i++)
            {
                string ip = ipBase + i.ToString();

                //var tcpClient = new TcpClient();
                //tcpClient.Connected += new PingCompletedEventHandler(p_PingCompleted);
                Ping ping = new Ping();
                ping.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
                countdown.AddCount();
                ping.SendAsync(ip, 20, ip);
            }
            countdown.Signal();
            countdown.Wait();
            sw.Stop();
            TimeSpan span = new TimeSpan(sw.ElapsedTicks);
            Console.WriteLine("Took {0} milliseconds. {1} hosts active.", sw.ElapsedMilliseconds, upCount);
            Console.ReadLine();
     

            return activeInterfaces;
        }
但当我调试代码时,它总是最终阻塞。不例外块和253 pings迭代完成后,再次无限循环@Evk和@jdweng请帮忙

@Evk这是它如何被卡住的图像

Ping SendAsync没有达到预期效果,您可以释放资源,但是您需要自己处理从另一个线程返回的答案,您需要挂接Ping Completed来处理答案

最好是通过在方法中调用ping和来创建方法的异步方法,并通过自己实现来在异步方法中调用方法


Ping SendAsync没有达到预期效果,您可以释放资源,但是您需要自己处理从另一个线程返回的答案,您需要挂接Ping Completed来处理答案

最好是通过在方法中调用ping和来创建方法的异步方法,并通过自己实现来在异步方法中调用方法


它不是在回答你的问题,而是在回答你的任务。我想,你是在使用IP请求来强制查看IP地址,最好使用地址解析协议(也称为ARP)

首先,创建存储数据的结构:

public struct MacIpPair : IEquatable<MacIpPair>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MacIpPair"/> struct.
    /// </summary>
    /// <param name="mac">The mac.</param>
    /// <param name="ip">The ip.</param>
    /// <param name="type">ARP record status</param>
    /// <exception cref="System.ArgumentException">Mac address needs to be provided - mac</exception>
    /// <exception cref="System.ArgumentException">IP address needs to be provided - ip</exception>
    public MacIpPair(string mac, string ip, ArpStatus type)
    {
        if (string.IsNullOrEmpty(mac))
        {
            throw new System.ArgumentException("Mac address needs to be provided", nameof(mac));
        }

        if (string.IsNullOrEmpty(ip))
        {
            throw new System.ArgumentException("IP address needs to be provided", nameof(ip));
        }

        MacAddress = mac;
        IpAddress = ip;
        Status = type;
    }

    /// <summary>
    /// The mac address
    /// </summary>
    /// <value>The mac address.</value>
    [NotNull]
    public string MacAddress { get; }

    /// <summary>
    /// The ip address
    /// </summary>
    /// <value>The ip address.</value>
    [NotNull]
    public string IpAddress { get; }
    /// <summary>
    /// The status of the ARP entry
    /// </summary>
    ArpStatus Status { get; }

    /// <summary>
    /// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
    /// </summary>
    /// <param name="obj">The object to compare with the current instance.</param>
    /// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
    public override bool Equals(object? obj)
    {
        return obj is MacIpPair pair && Equals(pair);
    }

    /// <summary>
    /// Indicates whether the current object is equal to another object of the same type.
    /// </summary>
    /// <param name="other">An object to compare with this object.</param>
    /// <returns><see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <see langword="false" />.</returns>
    public bool Equals(MacIpPair other)
    {
        return MacAddress == other.MacAddress &&
                IpAddress == other.IpAddress &&
                Status==other.Status
                ;
    }

    /// <summary>
    /// Returns a hash code for this instance.
    /// </summary>
    /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
    public override int GetHashCode()
    {
        return HashCode.Combine(MacAddress, IpAddress, Status);
    }

    /// <summary>
    /// Implements the == operator.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator ==(MacIpPair left, MacIpPair right)
    {
        return left.Equals(right);
    }

    /// <summary>
    /// Implements the != operator.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator !=(MacIpPair left, MacIpPair right)
    {
        return !(left == right);
    }
}

它不是在回答你的问题,而是在回答你的任务。我想,你是在使用IP请求来强制查看IP地址,最好使用地址解析协议(也称为ARP)

首先,创建存储数据的结构:

public struct MacIpPair : IEquatable<MacIpPair>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MacIpPair"/> struct.
    /// </summary>
    /// <param name="mac">The mac.</param>
    /// <param name="ip">The ip.</param>
    /// <param name="type">ARP record status</param>
    /// <exception cref="System.ArgumentException">Mac address needs to be provided - mac</exception>
    /// <exception cref="System.ArgumentException">IP address needs to be provided - ip</exception>
    public MacIpPair(string mac, string ip, ArpStatus type)
    {
        if (string.IsNullOrEmpty(mac))
        {
            throw new System.ArgumentException("Mac address needs to be provided", nameof(mac));
        }

        if (string.IsNullOrEmpty(ip))
        {
            throw new System.ArgumentException("IP address needs to be provided", nameof(ip));
        }

        MacAddress = mac;
        IpAddress = ip;
        Status = type;
    }

    /// <summary>
    /// The mac address
    /// </summary>
    /// <value>The mac address.</value>
    [NotNull]
    public string MacAddress { get; }

    /// <summary>
    /// The ip address
    /// </summary>
    /// <value>The ip address.</value>
    [NotNull]
    public string IpAddress { get; }
    /// <summary>
    /// The status of the ARP entry
    /// </summary>
    ArpStatus Status { get; }

    /// <summary>
    /// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
    /// </summary>
    /// <param name="obj">The object to compare with the current instance.</param>
    /// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
    public override bool Equals(object? obj)
    {
        return obj is MacIpPair pair && Equals(pair);
    }

    /// <summary>
    /// Indicates whether the current object is equal to another object of the same type.
    /// </summary>
    /// <param name="other">An object to compare with this object.</param>
    /// <returns><see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <see langword="false" />.</returns>
    public bool Equals(MacIpPair other)
    {
        return MacAddress == other.MacAddress &&
                IpAddress == other.IpAddress &&
                Status==other.Status
                ;
    }

    /// <summary>
    /// Returns a hash code for this instance.
    /// </summary>
    /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
    public override int GetHashCode()
    {
        return HashCode.Combine(MacAddress, IpAddress, Status);
    }

    /// <summary>
    /// Implements the == operator.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator ==(MacIpPair left, MacIpPair right)
    {
        return left.Equals(right);
    }

    /// <summary>
    /// Implements the != operator.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator !=(MacIpPair left, MacIpPair right)
    {
        return !(left == right);
    }
}

“但是Ping.SendAsync()卡在无限循环中”-这是怎么回事?您发送了多少Ping?你的循环看起来像是在发送253。如果服务器脱机或找不到,ping将不会完成并超时。如果ping得到响应或超时,回调方法将获得253次调用。问题是倒计时。信号();在代码中处于错误位置。当你得到一个例外,你不是倒计时。在最后一个街区的例外情况下移动到。看起来您遇到了异常。好的,谢谢@jdweng!您能添加一个简单的答案吗?@Evk被困在无限循环中,我的意思是调试器正在运行,但不会再遇到断点。。。我知道,这不是真正的无限loop@jdweng请看一下我的编辑“但是Ping.SendAsync()卡在无限循环中”-这是怎么回事?您发送了多少Ping?你的循环看起来像是在发送253。如果服务器脱机或找不到,ping将不会完成并超时。如果ping得到响应或超时,回调方法将获得253次调用。问题是倒计时。信号();在代码中处于错误位置。当你得到一个例外,你不是倒计时。在最后一个街区的例外情况下移动到。看起来您遇到了异常。好的,谢谢@jdweng!您能添加一个简单的答案吗?@Evk被困在无限循环中,我的意思是调试器正在运行,但不会再遇到断点。。。我知道,这不是真正的无限loop@jdweng请看我的编辑
public struct MacIpPair : IEquatable<MacIpPair>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MacIpPair"/> struct.
    /// </summary>
    /// <param name="mac">The mac.</param>
    /// <param name="ip">The ip.</param>
    /// <param name="type">ARP record status</param>
    /// <exception cref="System.ArgumentException">Mac address needs to be provided - mac</exception>
    /// <exception cref="System.ArgumentException">IP address needs to be provided - ip</exception>
    public MacIpPair(string mac, string ip, ArpStatus type)
    {
        if (string.IsNullOrEmpty(mac))
        {
            throw new System.ArgumentException("Mac address needs to be provided", nameof(mac));
        }

        if (string.IsNullOrEmpty(ip))
        {
            throw new System.ArgumentException("IP address needs to be provided", nameof(ip));
        }

        MacAddress = mac;
        IpAddress = ip;
        Status = type;
    }

    /// <summary>
    /// The mac address
    /// </summary>
    /// <value>The mac address.</value>
    [NotNull]
    public string MacAddress { get; }

    /// <summary>
    /// The ip address
    /// </summary>
    /// <value>The ip address.</value>
    [NotNull]
    public string IpAddress { get; }
    /// <summary>
    /// The status of the ARP entry
    /// </summary>
    ArpStatus Status { get; }

    /// <summary>
    /// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
    /// </summary>
    /// <param name="obj">The object to compare with the current instance.</param>
    /// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
    public override bool Equals(object? obj)
    {
        return obj is MacIpPair pair && Equals(pair);
    }

    /// <summary>
    /// Indicates whether the current object is equal to another object of the same type.
    /// </summary>
    /// <param name="other">An object to compare with this object.</param>
    /// <returns><see langword="true" /> if the current object is equal to the <paramref name="other" /> parameter; otherwise, <see langword="false" />.</returns>
    public bool Equals(MacIpPair other)
    {
        return MacAddress == other.MacAddress &&
                IpAddress == other.IpAddress &&
                Status==other.Status
                ;
    }

    /// <summary>
    /// Returns a hash code for this instance.
    /// </summary>
    /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
    public override int GetHashCode()
    {
        return HashCode.Combine(MacAddress, IpAddress, Status);
    }

    /// <summary>
    /// Implements the == operator.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator ==(MacIpPair left, MacIpPair right)
    {
        return left.Equals(right);
    }

    /// <summary>
    /// Implements the != operator.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator !=(MacIpPair left, MacIpPair right)
    {
        return !(left == right);
    }
}
/// <summary>
/// Gets all mac addresses and IP PAIRS visible to the computer.
/// </summary>
/// <remarks>
/// This will use RRP broadcast to obtain the mac addresses for all devices connected with the DHCP server
/// </remarks>
/// <returns>List&lt;MacIpPair&gt;.</returns>
public static List<MacIpPair> GetAllMacAddressesAndIpPairs()
{
    try
    {
        List<MacIpPair> mip = new List<MacIpPair>();
        using System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
        pProcess.StartInfo.FileName = "arp";
        pProcess.StartInfo.Arguments = "-a ";
        pProcess.StartInfo.UseShellExecute = false;
        pProcess.StartInfo.RedirectStandardOutput = true;
        pProcess.StartInfo.CreateNoWindow = true;
        pProcess.Start();
        pProcess.WaitForExit();
        string cmdOutput = pProcess.StandardOutput.ReadToEnd();
        string pattern = @"(?<ip>([0-9]{1,3}\.?){4})\s*(?<mac>([a-f0-9]{2}-?){6})";

        foreach (Match? m in Regex.Matches(cmdOutput, pattern, RegexOptions.IgnoreCase))
        {
            if (m is null)
                continue;
            mip.Add(new MacIpPair(m.Groups["mac"].Value, m.Groups["ip"].Value, ArpStatus.Static));
        }

        return mip;
    }
    catch (Exception e)
    {
        Walter.TicketService.PostException(e);
        throw;
    }
}
[DllImport("IpHlpApi.dll", EntryPoint = "GetIpNetTable")]
[return: MarshalAs(UnmanagedType.U4)]
internal static extern int GetIpNetTable(IntPtr pIpNetTable, [MarshalAs(UnmanagedType.U4)] ref int pdwSize, bool bOrder);