Correctly Implementing PingAsync In A Function?

  • (2 Pages)
  • +
  • 1
  • 2

17 Replies - 2049 Views - Last Post: 03 March 2013 - 07:25 PM Rate Topic: -----

#1 adn258  Icon User is offline

  • D.I.C Addict

Reputation: 11
  • View blog
  • Posts: 763
  • Joined: 31-August 11

Correctly Implementing PingAsync In A Function?

Posted 25 February 2013 - 05:24 PM

So what I'm using for now is something like

 public string Ping_Host(int buffer_size,int timeout)
        {
            string Strping_Reply = "";
            IPAddress ip = this.Get_IP_From_Host(this.strHostname);
            byte[] buffer = new byte[buffer_size];
            if (ip != null)
            {
                using (Ping p = new Ping())
                {
                   using( AutoResetEvent are = new AutoResetEvent(false))
                    {

                    p.SendAsync(ip, timeout, buffer, new PingOptions { Ttl = 64, DontFragment = true }, are);
                    p.PingCompleted += (o, e) =>
                        {
                            Strping_Reply = e.Reply.Status.ToString();
                        };
                    }
                }
                return Strping_Reply;
            }
            else
            { return null; }
            
       } 



I want for this example this function to return the reply Status as a string in that method. What happens instead is there isn't a wait or something?? If there is any kind of pause like a messagebox or anything before return Strping IT WILL return the status correctly.

I thought that AutoResetEvent was supposed to cause this to wait but it doesn't? This is highly confusing what am I doing wrong? I appreciate the help guys!!

Is This A Good Question/Topic? 0
  • +

Replies To: Correctly Implementing PingAsync In A Function?

#2 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 25 February 2013 - 06:41 PM

Nowhere in your code do you wait for the event, and nowhere in your code do you set the event. Reading the documentation usually helps. Look the MSDN sample even shows waiting for the event and setting the event. http://msdn.microsof...y/a63bsyf0.aspx
Was This Post Helpful? 0
  • +
  • -

#3 adn258  Icon User is offline

  • D.I.C Addict

Reputation: 11
  • View blog
  • Posts: 763
  • Joined: 31-August 11

Re: Correctly Implementing PingAsync In A Function?

Posted 25 February 2013 - 11:12 PM

View PostSkydiver, on 25 February 2013 - 06:41 PM, said:

Nowhere in your code do you wait for the event, and nowhere in your code do you set the event. Reading the documentation usually helps. Look the MSDN sample even shows waiting for the event and setting the event. http://msdn.microsof...y/a63bsyf0.aspx


I've looked at that and it's confusing because I don't understand this AutoResetEvent I've even looked at the documentation for that it makes 0 sense to me. What does that do what is it for?
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 05:58 AM

Did you look at the documentation at: http://msdn.microsof...resetevent.aspx

Anyway, the basic idea is this:
// this matches waiter = new AutoResetEvent(false);
bool waiter = false;


//
// In the thread where you want to wait.
// Your Ping_Host(), for example.
//

// this matches waiter.WaitOne();
while (waiter == false)
    ; // do nothing


//
// In the thread where async work happens.
// Your PingCompleted event handler for example.
//

// this matches waiter.Set();
waiter = true;



The while loop above is called a busy wait. It is eating up CPU resources doing nothing except waiting for the boolean to flip to true. The use of a WaitHandle.WaitOne() is an efficient way to wait for the "boolean" to flip because instead of eating up CPU doing nothing, it actually yields the CPU to other threads and processes. When the "boolean" flips, the OS knows to go back to that particular thread and let it continue to run.

I put "boolean" in quotes because instead of a true C# bool being used, an OS primitive object meant to handle asynchronous communication is used. These primitive objects are thread safe, unlike the code above which could potentially suffer from race conditions, and compiler optimizations which may decide to use a register instead of re-reading the memory block.
Was This Post Helpful? 1
  • +
  • -

#5 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2271
  • View blog
  • Posts: 9,500
  • Joined: 29-May 08

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 07:45 AM

That api returns a Task, why wait for it to complete? Or use the synchronous version.

This post has been edited by AdamSpeight2008: 26 February 2013 - 07:51 AM

Was This Post Helpful? 0
  • +
  • -

#6 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 07:58 AM

I'm lost. As best as I can see, SendAsync() variants all return void. What am I missing?
http://msdn.microsof....sendasync.aspx

Anyway, AdamSpeight2008, is correct. It seems like you are using ping in a synchronous manner, so might as well use the synchronous version.
Was This Post Helpful? 0
  • +
  • -

#7 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2271
  • View blog
  • Posts: 9,500
  • Joined: 29-May 08

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 08:02 AM

I think that the Task returning method maybe .net4.5 or higher. (MSDN)
Was This Post Helpful? 0
  • +
  • -

#8 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 08:13 AM

Oh, I see... SendPingAsync() vs. SendAsync().
Was This Post Helpful? 0
  • +
  • -

#9 adn258  Icon User is offline

  • D.I.C Addict

Reputation: 11
  • View blog
  • Posts: 763
  • Joined: 31-August 11

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 02:02 PM

Yes this is very confusing so I've even tried the following

 public string Ping_Host(int buffer_size,int timeout)
        {
            string Strping_Reply = "";
            IPAddress ip = this.Get_IP_From_Host(this.strHostname);
            byte[] buffer = new byte[buffer_size];
            if (ip != null)
            {
                AutoResetEvent are = new AutoResetEvent(false);
                    using (Ping p = new Ping())
                    {
                        p.SendAsync(ip, timeout, buffer, new PingOptions { Ttl = 64, DontFragment = true }, are);
                        are.WaitOne();
                        p.PingCompleted += (o, e) =>
                            {
                                Strping_Reply = e.Reply.Status.ToString();
                                ((AutoResetEvent)e.UserState).Set();
                            };

                    }
                return Strping_Reply;
            }
            else
            { return null; }
            
       } 



Which is very close only implemented differently than the microsoft documentation example but the program deadlocks when this code is used; literally. Obviously I'm doing something wrong what's your advice Skydiver? Maybe I should use SendPingAsync
Was This Post Helpful? 0
  • +
  • -

#10 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 02:09 PM

Well, of course, it is deadlocking because you are waiting on the same thread that you were going to make the call to setup the event handler which sets the event that you are waiting for.
Was This Post Helpful? 0
  • +
  • -

#11 adn258  Icon User is offline

  • D.I.C Addict

Reputation: 11
  • View blog
  • Posts: 763
  • Joined: 31-August 11

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 02:14 PM

View PostSkydiver, on 26 February 2013 - 02:09 PM, said:

Well, of course, it is deadlocking because you are waiting on the same thread that you were going to make the call to setup the event handler which sets the event that you are waiting for.


I know I'm obviously not getting something man...I didn't see that in the example but apparently I'm supposed to do the ping send on another threat entirely?
Was This Post Helpful? 0
  • +
  • -

#12 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 03:06 PM

Put lines 13-17 before line 11, and you should fix the deadlock.

Remember what I wrote in post #4 about how wait works. With your code on post #9, you essentially have:
bool waiter = false;

while (!waiter)
    ;

waiter = true;



There is no way to make it line 6 because of the loop on line 3-4.
Was This Post Helpful? 0
  • +
  • -

#13 adn258  Icon User is offline

  • D.I.C Addict

Reputation: 11
  • View blog
  • Posts: 763
  • Joined: 31-August 11

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 05:32 PM

View PostSkydiver, on 26 February 2013 - 03:06 PM, said:

Put lines 13-17 before line 11, and you should fix the deadlock.

Remember what I wrote in post #4 about how wait works. With your code on post #9, you essentially have:
bool waiter = false;

while (!waiter)
    ;

waiter = true;



There is no way to make it line 6 because of the loop on line 3-4.


See that's what I thought too actually and I put the event before line 11 and IT STILL DEADLOCKS just like it always has which makes no sense at all from what I can see?

View PostSkydiver, on 26 February 2013 - 03:06 PM, said:

Put lines 13-17 before line 11, and you should fix the deadlock.

Remember what I wrote in post #4 about how wait works. With your code on post #9, you essentially have:
bool waiter = false;

while (!waiter)
    ;

waiter = true;



There is no way to make it line 6 because of the loop on line 3-4.


See that's what I thought too actually and I put the event before line 11 and IT STILL DEADLOCKS just like it always has which makes no sense at all from what I can see?

now I have
 public string Ping_Host(int buffer_size, int timeout)
        {
            string Strping_Reply = "";
            IPAddress ip = this.Get_IP_From_Host(this.strHostname);
            byte[] buffer = new byte[buffer_size];
            if (ip != null)
            {
                AutoResetEvent are = new AutoResetEvent(false);
                Ping p = new Ping();
                
                    p.PingCompleted += (o, e) =>
                    {
                        Strping_Reply = e.Reply.Status.ToString();
                        ((AutoResetEvent)e.UserState).Set();
                    };
                    p.SendAsync(ip, timeout, buffer, new PingOptions { Ttl = 64, DontFragment = true }, are);
                    are.WaitOne();

                
                return Strping_Reply;
            }
            else
            { return null; }

        } 


I even got rid of using around everything as I don't even want to worry about that yet when something like this doesn't even work at all

This post has been edited by adn258: 26 February 2013 - 05:34 PM

Was This Post Helpful? 0
  • +
  • -

#14 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 06:16 PM

If you set a breakpoint on line 13, does it ever get called?

Anyway, since you are using ping practically in a synchronous manner, use the synchronous call instead.
Was This Post Helpful? 0
  • +
  • -

#15 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3666
  • View blog
  • Posts: 11,497
  • Joined: 05-May 12

Re: Correctly Implementing PingAsync In A Function?

Posted 26 February 2013 - 08:04 PM

This seems to work for me without any deadlock:
using System;
using System.Diagnostics;
using System.Data;
using System.Text;
using System.Net;
using System.Threading;
using System.Net.NetworkInformation;

namespace SimpleCsConsole2012
{

public class Program
{
    static void Main()
    {
        IPAddress ip = new IPAddress(0x7F000001);
        byte[] buffer = new byte[8192];
        if (ip != null)
        {
            AutoResetEvent are = new AutoResetEvent(false);
            Ping p = new Ping();

            p.PingCompleted += (o, e) =>
            {
                Console.WriteLine("Ping completed...");
                ((AutoResetEvent)e.UserState).Set();
            };
            p.SendAsync(ip, 7000, buffer, new PingOptions { Ttl = 64, DontFragment = true }, are);
            Console.WriteLine("Waiting...");
            are.WaitOne();
            Console.WriteLine("Done waiting...");
        }
        Console.WriteLine("Done.");
    }
}

}


Was This Post Helpful? 1
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2