Nandun
Nandun

Reputation: 2042

Ping.SendAsync does not hit the call back PingCompletedEventHandler

I'm having some trouble with SendAsync method when passing an invalid IP - 0.0.0.51

Problem is, the Call back method (pingSender_PingCompleted) does not even get invoked. I do not see any errors what so ever.

IPAddress.TypeParse finds this IP as a "valid" IP.

Here is my code; please let me know what I'm not seeing here.

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");
        }
    }
}

Please note that I can't:

  1. Have any kind of control over what comes through ipAddress

  2. Complicate my code by using Regex

Upvotes: 1

Views: 2342

Answers (1)

Aoi Karasu
Aoi Karasu

Reputation: 3825

I've tested your two methods in a simple console application, and I'm getting PingException for 0.0.0.51 just as itsme86 commented.

This is my guess on what is happening: your comment "I'm expecting this method to be called 100s of times simultaneously." plus pingSender_PingCompleted not being invoked implicates that you're invoking the PingStore method on a worker thread (e.g. using ThreadPool). This would be the reason why you are unable to catch the PingException on your main thread while pingSender_PingCompleted is never invoked due to the exception.

UPDATE

In your comment you wrote "FYI i'm on .Net 4.0.".

Are you 100% sure, your app targets v4.0, not v3.5 or earlier?

I was able to reproduce your problem using your exact code, but when targeting .NET Framework v3.5 (for v4.0 exception is thrown using your code).

I did some digging in System.dll for both Framework versions and this is what I found:

  • Both Framework versions inside the Ping class in method private PingReply InternalSend(...) use native method num = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2.
  • In case of error num is set to 0, and I found out that each Framework version handles this situation differently.

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);
}

As you can see in the code snippets above, in .NET v4.0 you should be able to catch the exception, while in .NET v3.5 all native WIN32 errors are handled silently.

Upvotes: 3

Related Questions