1

I'm having trouble with a really simple program I'm making. I want it so that when I click btnPing, it will send a ping to google.com every 1 second and return the ping in milliseconds. It works perfectly until I want to loop the action. Outside of the while loop, the code works, but requires me to click the button every time I want to send a ping. But when I put the code in a loop, it freezes. I've tried it with a for loop and a while loop. The program is returning no errors. What is making my program freeze?

Ping pingClass = new Ping();

private void btnPing_Click(object sender, EventArgs e)
{
    while (true)
    {
        PingReply pingReply = pingClass.Send("google.com");
        rtxtPing.Text = rtxtPing.Text + "\r\n" + (pingReply.RoundtripTime.ToString() + "ms");
        System.Threading.Thread.Sleep(1000);
    }
}
Jerry
  • 70,495
  • 13
  • 100
  • 144
  • Aside from the answers below, stylistically, I would look at scheduling the call to ping on a 1 second timer, rather than using a while/sleep loop. Even on a background thread, while/sleep is a bad practice to get into. http://stackoverflow.com/questions/2822441/system-timers-timer-threading-timer-vs-thread-with-whileloop-thread-sleep-for – Alan May 26 '13 at 19:33
  • @Alan I agree. Another way would be to have an event set up on a timer to do the ping and have the button simply enable the timer. – mclaassen May 26 '13 at 19:38

3 Answers3

3

You are entering an infinite while loop on the UI thread. Sleep is a blocking call, i.e. it does not "free up" the thread to continue to do other work.

Here is one solution using events:

        public delegate void PingReceivedEventHandler(int time);

        public event PingReceivedEventHandler PingReceived;

        public Form1()
        {
            InitializeComponent();

            PingReceived += new PingReceivedEventHandler(Form1_PingReceived);
        }

        void Form1_PingReceived(int time)
        {
            //do something with val
        }

        private void button1_Click(object sender, EventArgs e)
        {
            (new Thread(() =>
                {
                    while(true)
                    {
                        int time;

                        //get value here

                        PingReceived(time);
                    }
                }
            )).Start();
        }
mclaassen
  • 5,018
  • 4
  • 30
  • 52
3

The reason is because your loop is blocking the UI, which in turn cannot update itself and seems to be frozen (while in fact the program is executing the ping in the loop). You have to run it asynchronously (i.e. in parallel to the UI code), in a separate thread. To get started, see the example provided with the BackgroundWorker class.

Ondrej Tucny
  • 27,626
  • 6
  • 70
  • 90
0

Since your while loop is executed in non stop manner you dont see anything on the screen, It feels like screen is freezed. You may get the desired result by using Timer instead of while loop. I have tested this code, it works fine.

Place the following code within button click event

private void button2_Click(object sender, EventArgs e)
{         

    Timer timer = new Timer { Interval = 1000, Enabled = true };
    timer.Tick += new EventHandler(PingTest);            
}

Add a method with the ping logic as follows

public void PingTest(object sender, EventArgs e)
{
    Ping pingClass = new Ping();

    PingReply pingReply = pingClass.Send("google.com");
    rtxtPing.Text = rtxtPing.Text + "\r\n" + (pingReply.RoundtripTime.ToString() + "ms");        
}
Kurubaran
  • 8,696
  • 5
  • 43
  • 65