4

So I have this code below. I found a preview post and was working of it from here. But for some reason it is not cycling through and updating the cells with the reply status. It only updates the last ip in the list.

private static void ping_PingCompleted(object sender, PingCompletedEventArgs e)
{
    var reply = e.Reply;
    DataGridViewRow row = e.UserState as DataGridViewRow;
    DataGridViewCell PingStat = row.Cells["cPing"];
    if (!(reply == null))
    {
        switch (reply.Status)
        {
            case IPStatus.Success:
               PingStat.Value = string.Format("Reply from {0}: bytes={1} time={2}ms TTL={3}", reply.Address, reply.Buffer.Length, reply.RoundtripTime, reply.Options.Ttl);
               break;
            case IPStatus.TimedOut:
               PingStat.Value = "Connection has timed out...";
               break;
            default:
               PingStat.Value = string.Format("Ping failed: {0}", reply.Status.ToString());
               break;
        }
    }
}


private void bPing_Click(object sender, EventArgs e)
{
    String ip;
    Ping ping = new Ping();
    foreach (DataGridViewRow row in dgvData.Rows)
    {
        if(!row.IsNewRow)
        {
            ip = row.Cells["cIPAddress"].Value.ToString();

            ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);

            ping.SendAsync(ip, 1000, row);

            System.Threading.Thread.Sleep(5);
        }
    }
}

What am I doing incorrect? I thought with adding row to ping.SendAsync it would track all reply to corresponding ip/row?

UPDATED Code I am working with

        private static void ping_PingCompleted(object sender, PingCompletedEventArgs e)
    {
        var reply = e.Reply;
        DataGridViewRow row = e.UserState as DataGridViewRow;
        DataGridViewCell PingStat = row.Cells["cPing"];
        if (reply != null)
        {
            switch (reply.Status)
            {
                case IPStatus.Success:
                    PingStat.Value = string.Format("Reply from {0}: bytes={1} time={2}ms TTL={3}", reply.Address, reply.Buffer.Length, reply.RoundtripTime, reply.Options.Ttl);
                    break;
                case IPStatus.TimedOut:
                    PingStat.Value = "Connection has timed out...";
                    break;
                default:
                    PingStat.Value = string.Format("Ping failed: {0}", reply.Status.ToString());
                    break;
            }
        }
    }
    private void bPing_Click(object sender, EventArgs e)
    {
        foreach (DataGridViewRow row in dgvData.Rows)
        {
            if (!row.IsNewRow)
            {
                Debug.WriteLine("Rows");
                String ip;
                Ping ping = new Ping();
                ip = row.Cells["cIPAddress"].Value.ToString();
                ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);

                ping.SendAsync(ip, 1000, row);

                System.Threading.Thread.Sleep(5);
            }
        }
    }
Zach Schulze
  • 304
  • 1
  • 4
  • 17

2 Answers2

1

I think the issue is that you have one Ping and one IP and these keep getting reset until the last row. If you move those vars into the foreach loop then each row in the DataGridView will have its "own" Ping and ip and so you will not have the issue of each row effectively undoing the previous.

private void bPing_Click(object sender, EventArgs e)
{
    foreach (DataGridViewRow row in dgvData.Rows)
    {
        if(!row.IsNewRow)
        {
            String ip;
            Ping ping = new Ping();
            ip = row.Cells["cIPAddress"].Value.ToString();
            ping.PingCompleted += new   PingCompletedEventHandler(ping_PingCompleted);

            ping.SendAsync(ip, 1000, row);

            System.Threading.Thread.Sleep(5);
        }
    }
}

Also, I am unfamiliar with "Ping", but you might want to see if it needs to be disposed of, or put it in a Using loop.

Also there is no need to cast a row to a row.

Max von Hippel
  • 2,856
  • 3
  • 29
  • 46
  • Went straight over my head. I will definitely do this and see what happens. – Zach Schulze Aug 07 '15 at 06:14
  • No worries! If it doesn't work let me know and I'll come up with a better answer haha – Max von Hippel Aug 07 '15 at 06:16
  • 1
    Sadly, that appears not to be the issue. Or at least not the only one. It still gives the same results of only filling in the info for the last ip in my datagridview – Zach Schulze Aug 07 '15 at 06:22
  • Have you debugged to see if it is actually iterating through all the rows? I would put a Debug.WriteLine("literally anything as long as you can recognize the text in the output"); in the foreach loop. Then if that shows up for every row, put it in the if(!row.IsNewRow) loop and see if it shows up for each one. – Max von Hippel Aug 07 '15 at 06:27
  • Yes sir, I had 3 rows in my DataGridView and it wrote out "I Exist" three times. So I know its rolling through each row. I think it might have to do with the third parameter of SendAsync but not sure. Still troubleshooting – Zach Schulze Aug 07 '15 at 06:30
  • Ok then the next thing is to test ping_PingCompleted . Just because only one cell is updated doesn't mean ping_PingCompleted isn't happening many times. – Max von Hippel Aug 07 '15 at 06:32
  • This is the first posting I began to build from. But didn't want to revive such and old post. http://stackoverflow.com/questions/9748245/how-to-use-ping-sendasync-working-with-datagridview – Zach Schulze Aug 07 '15 at 06:32
  • 1
    @ZachSchulze Are you sure you're using the same code which Max von Hippel has given? I still believe you've not created new instance of Ping class per row – Sriram Sakthivel Aug 07 '15 at 06:32
  • Well @ZachSchulze says he used my code and I see no reason not to believe him.. One possibility I see is maybe there's something fishy with that e.userState row stuff – Max von Hippel Aug 07 '15 at 06:35
  • Yes. I've updated the first post with a few changes as suggested. But yields the same results – Zach Schulze Aug 07 '15 at 06:35
  • This is where you got the code you're working with? http://stackoverflow.com/questions/9748245/how-to-use-ping-sendasync-working-with-datagridview – Max von Hippel Aug 07 '15 at 06:41
  • Yes sir, That is the link I provided a few comments ago I believe. – Zach Schulze Aug 07 '15 at 06:43
  • Ok provided explanation of alternative possible issue (sorry if shooting in the dark a bit here, hopefully helpful haha). Also please debug in your listener ping_PingCompleted and see if it is being called only once or for every row (per my previous comment). – Max von Hippel Aug 07 '15 at 06:52
  • So debugged it. And it loops to it each time correctly. But for some reason result is returning null except for the last IP in the list. In which it returns correct information. – Zach Schulze Aug 07 '15 at 06:56
  • Yes I did. And it did change anything. As there is no e.UserToken. It is only e.UserState – Zach Schulze Aug 07 '15 at 13:29
0

What about this:

private void bPing_Click(object sender, EventArgs e) {
    foreach (DataGridViewRow row in dgvData.Rows) {
        try {
            Ping pinger = new Ping();
            PingReply reply = await pinger.SendPingAsync(row.Cells["cIPAddress"].Value.ToString(),1000);
            switch (reply.Status) {
                // do your stuff here
            }
        } catch (PingException) {
            // Handle exception here
        }
    }
}
Igor Gorjanc
  • 535
  • 4
  • 17
  • This yields the same results. It seems it pings runs through the code for them all. But only the last ip on the list actually returns something other than null – Zach Schulze Aug 07 '15 at 13:35