Question

  • Problem: When Pinging an offline device it takes 10-15 seconds.

  • Goal: I would like to end/kill/stop or what ever is necessary the background worker if the ping or backgroundworker runs for longer then 5 seconds. Any suggestions how i can do this?

Currently when i ping a device that's online it reply back within the first second.

private void backgroundWorkerPing_DoWork(object sender, DoWorkEventArgs e)
{
    string pcName = e.Argument.ToString();

    lblIPAddress.Invoke((Action)(() => lblIPAddress.ForeColor = Color.Black));

    lblStatus.GetCurrentParent().Invoke((Action)(() => lblStatus.Text = String.Format("Pinging {0}", pcName)));                

    string ipAddress = GetSinglePing(pcName);                       
    e.Result = ipAddress;
}

private string GetSinglePing(string pcName)
{
    Network net = new Network();
    return net.Pinger(pcName);
}

public class Network
{
    //My Ping Method
    public string Pinger(string pcName, int bufferSize = 32)
    {
        Ping ping = new Ping();
        byte[] buffer = new byte[bufferSize];
        PingOptions pingOpt = new PingOptions(64, true);            

        try
        {
            PingReply pingReply = ping.Send(pcName, 100, buffer, pingOpt);

            if (pingReply.Status == IPStatus.Success)
            {
                return pingReply.Address.ToString();
            }
            else
            {
                return "Offline";
            }
        }
        catch
        {
            return "Offline";
        }
    }            
}
Was it helpful?

Solution

Edit again:

As stated in my previous "edit", you already have ping timeout set in your code. So you really should not have 5...15 second delays for your operation. Maybe problem is somewhere else?

For example, take the following code (simple console app), which iterates list of IPs and then displays ping results for each, in format of IP - STATE - TIME USED

public class Program
{
    private static void Main(string[] args)
    {
        var p = new Program();
        p.PingPong();
        Console.ReadLine();
    }

    private void PingPong()
    {
         var ips = new List<string>()
            {
                "43.128.240.28",
                "159.203.123.166",
                ... 30 in total in this test ...
                "201.131.43.87",
                "108.232.183.145"
            };

        foreach (var ip in ips)
        {
            string ip1 = ip;
            Task.Factory.StartNew(async () =>
                {
                    var newtwork = new Network();
                    var start = DateTime.Now;
                    string ping = newtwork.Pinger(ip1);
                    Console.WriteLine("{0} - {1} - {2}ms", ip, ping, (DateTime.Now - start).TotalMilliseconds);
                });
        }
    }
}

Outputs more or less the following.

75.146.125.27 - Offline - 998.0982ms
190.37.198.208 - Offline - 978.329ms
90.82.250.179 - Offline - 975.3303ms
141.231.190.96 - Offline - 998.3851ms
38.89.231.171 - Offline - 976.3265ms
183.179.51.148 - Offline - 999.1762ms
125.238.115.199 - Offline - 977.1139ms
201.131.43.87 - Offline - 975.1229ms
154.165.188.89 - Offline - 978.1232ms
86.8.40.161 - Offline - 979.1236ms
108.232.183.145 - Offline - 998.6617ms

None of the requests took more than one (1) second, which was the timeout I set myself.

So answer is: Launch each request as new task and ditch the backgroundworker alltogether, setting ping timeout to the level you actually need, and delegate response back to UI thread using .BeginInvoke() if needed (not Invoke()).

Hope this helps you forward!

Edit:

Ok, so I see you already set the timeout to 100ms so it shouldn't take long. But then you do the following:

PingReply pingReply;
do
{
    pingReply = ping.Send(pcName, 100, buffer, pingOpt);                    
}
while(pingReply.Status != IPStatus.Success);
return pingReply.Address.ToString();    

Would it help you just get rid of the loop there?


Maybe you could launch all your pings as separate tasks and just let them live as long as needed?

Task.Factory.StartNew(() => Pinger("pcName"));

OTHER TIPS

using System.Net.NetworkInformation;

Ping pingSender = new Ping ();
        PingOptions options = new PingOptions ();
        options.DontFragment = true;
        string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        byte[] buffer = Encoding.ASCII.GetBytes (data);
        int timeout = 1000; //to timeout after 1s
        PingReply reply = pingSender.Send (args[0], timeout, buffer, options);
        if (reply.Status == IPStatus.Success)
        {
            Console.WriteLine ("Address: {0}", reply.Address.ToString ());
            Console.WriteLine ("RoundTrip time: {0}", reply.RoundtripTime);
            Console.WriteLine ("Time to live: {0}", reply.Options.Ttl);
            Console.WriteLine ("Don't fragment: {0}", reply.Options.DontFragment);
            Console.WriteLine ("Buffer size: {0}", reply.Buffer.Length);
        }

More examples in http://msdn.microsoft.com/en-us/library/system.net.networkinformation.ping(v=vs.110).aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top