0

I found a code to check the connectivity of multiple host that read the addresses from a list and ping them as an asynchronous manner and processes the result.

When I use a predefined list,for example:

public static List<string> addresses = new List<string> { "172.20.74.1", "192.168.1.103", "192.168.1.104", "192.168.1.105"};

everything works properly, but when I read this list from Database, the NullReferenceException occurs. Can someone help me solve this problem?

using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Data.SqlClient;
using System.Collections.Generic;
using System;

namespace asyncPing
{
    class Program
    {
        public static List<string> addresses = getNetAddress();
        //public static List<string> addresses = new List<string> { "172.20.74.1", "192.168.1.103", "192.168.1.104", "192.168.1.105"};
        static void Main(string[] args)
        {
            List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();

            foreach (var address in addresses)
            {
                Console.WriteLine(address);

            }
            foreach (var address in addresses)
            {
                pingTasks.Add(PingAsync(address));
            }

            //Wait for all the tasks to complete
            Task.WaitAll(pingTasks.ToArray());

            //Now you can iterate over your list of pingTasks
            foreach (var pingTask in pingTasks)
            {

                Console.WriteLine(pingTask.Result.Address + "\t" + pingTask.Result.Status);
                if (pingTask.Result.Status != IPStatus.Success)
                {
                    //Do Some Thing
                }
            }
            Console.ReadLine();
        }

        public static List<string> getNetAddress()
        {
            List<string> addr = new List<string>();
            string connetionString = @"Data Source=localhost;Initial Catalog=AlarmsDB;Persist Security Info=True;User ID=sa;Password=123456";



            using (SqlConnection myConnection = new SqlConnection(connetionString))
            {
                //Console.WriteLine("Connection Open  !");
                string oString = "Select ip_address from Networks";
                SqlCommand oCmd = new SqlCommand(oString, myConnection);

                myConnection.Open();
                using (SqlDataReader oReader = oCmd.ExecuteReader())
                {
                    while (oReader.Read())
                    {
                        addr.Add(oReader["ip_address"].ToString());
                    }

                    myConnection.Close();
                }
            }

            return addr;
        }
        static Task<PingReply> PingAsync(string address)
        {
            var tcs = new TaskCompletionSource<PingReply>();
            Ping ping = new Ping();
            ping.PingCompleted += (obj, sender) =>
            {
                tcs.SetResult(sender.Reply);
            };
            ping.SendAsync(address, new object());
            return tcs.Task;
        }
    }
}

The exception occures in line:

Console.WriteLine(pingTask.Result.Address + "\t" + pingTask.Result.Status);

It seems the result of async pings method appears to null. I don't know why when the same input passed from database, the result the output changes?

enter image description here

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Hamid Mousavi
  • 223
  • 2
  • 10
  • One recommendation, Please use `WhenAll` in place of `WaitAll` – Vivek Nuna Oct 16 '21 at 20:40
  • Change `ping.SendAsync(address, new object());` to `await ping.SendAsync(address, new object());` - does that fix the issue? – Ermiya Eskandary Oct 16 '21 at 20:50
  • Could you try replacing the line `pingTasks.Add(PingAsync(address));` with this `pingTasks.Add(new Ping().SendPingAsync(address));`, to see if it makes any difference? – Theodor Zoulias Oct 16 '21 at 21:20
  • Related: [How can I make many pings asynchronously at the same time?](https://stackoverflow.com/questions/22078510/how-can-i-make-many-pings-asynchronously-at-the-same-time) – Theodor Zoulias Oct 16 '21 at 21:53

1 Answers1

0

Thanks to all the guys for their suggestions to solve the problem

Finally i found the problem source after 2 day

After i triming the ip address before pass it to asyncPing method the problem resolved.

I saved the ip address ​​as strings in the database but I do not know why I have to trim them after reading

I was able to solve the problem by changing the line below:

using (SqlDataReader oReader = oCmd.ExecuteReader())
                {
                    while (oReader.Read())
                    {                        
                 addr.Add(oReader["ip_address"].ToString().Trim());
                    }

                    myConnection.Close();
                }
Hamid Mousavi
  • 223
  • 2
  • 10
  • 1
    Maybe the database column is of type `char` instead of `varchar`. – Theodor Zoulias Oct 17 '21 at 08:26
  • The Column type is nchar(20). Are you think the data type to storing the ip address is wrong? – Hamid Mousavi Oct 17 '21 at 20:57
  • 1
    From [here](https://stackoverflow.com/questions/176514/what-is-the-difference-between-char-nchar-varchar-and-nvarchar-in-sql-server/6771680#6771680): *`nchar` - adds trailing spaces to the data. `nvarchar` - does not add trailing spaces to the data.* The most efficient datatype for storing IP addresses is probably `varbinary(16)`, as explained [here](https://stackoverflow.com/questions/1385552/datatype-for-storing-ip-address-in-sql-server). – Theodor Zoulias Oct 17 '21 at 22:30
  • 1
    Theodor Zoulias, thank you for your guidance and suggestions. With your guidance, I learned something new – Hamid Mousavi Oct 18 '21 at 02:46