Ping.SendAsync没有点击回调PingCompletedEventHandler

时间:2014-02-24 22:50:39

标签: c# .net asynchronous ping sendasync

传递无效的IP时,我遇到了SendAsync方法的问题 - 0.0.0.51

问题是,甚至没有调用回调方法(pingSender_PingCompleted)。我没有看到任何错误。

IPAddress.TypeParse将此IP视为“有效”IP。

这是我的代码;请让我知道我在这里没有看到的。

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program c = new Program();

            try
            {
                c.PingStore("0.0.0.51");
                Console.WriteLine("Pinged without exceptions");
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex.Message);
            }
        }

        private void PingStore(string ipAddress)
        {
            Ping pingSender = new Ping();

            pingSender.PingCompleted += new PingCompletedEventHandler(pingSender_PingCompleted);

            pingSender.SendAsync(ipAddress, null);
        }

        private void pingSender_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            Console.WriteLine("PingCompleted invoked. continue to be happy");
        }
    }
}

请注意,我不能:

  1. 对ipAddress的内容有任何控制

  2. 使用Regex

  3. 使我的代码复杂化

1 个答案:

答案 0 :(得分:3)

我已经在一个简单的控制台应用程序中测试了你的两个方法,而我正在PingException获取0.0.0.51,就像 itsme86 一样。

这是我对正在发生的事情的猜测:你的评论“我希望这种方法可以同时被调用100次。”加上pingSender_PingCompleted未被调用意味着您正在工作线程上调用PingStore方法(例如,使用ThreadPool)。这就是为什么你不能在你的主线程上捕获PingException而因为异常从未调用pingSender_PingCompleted的原因。

<强>更新

在你的评论中你写道“我在.Net 4.0上。”。

您是否100%确定,您的应用是针对v4.0,而不是v3.5或更早版本?

我能够使用您的确切代码重现您的问题,但是在针对.NET Framework v3.5时(使用您的代码抛出v4.0异常)。

我在System.dll中为两个Framework版本做了一些挖掘,这就是我发现的:

  • 方法Pingprivate PingReply InternalSend(...)类内的两个Framework版本都使用本机方法num = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2
  • 如果错误num设置为0,我发现每个Framework版本都以不同的方式处理这种情况。

Framework v3.5 / 2.0:

if (num == 0)
{
    num = Marshal.GetLastWin32Error();
    if (num != 0)
    {
        this.FreeUnmanagedStructures();
        return new PingReply((IPStatus)num);
    }
}

Framewrk v4.0 / 4.5:

if (num == 0)
{
    num = Marshal.GetLastWin32Error();
    if (async && (long)num == 997L)
    {
        return null;
    }
    this.FreeUnmanagedStructures();
    this.UnregisterWaitHandle();
    if (async || num < 11002 || num > 11045)
    {
        /* NOTE! This throws the exception for 0.0.0.51 address that you're not getting */
        throw new Win32Exception(num);
    }
    return new PingReply((IPStatus)num);
}

正如您在上面的代码片段中所看到的,在.NET v4.0中,您应该能够捕获异常,而在.NET v3.5中,所有本机WIN32错误都是以静默方式处理的。