5

I wrote this code that works perfectly, but I fear that ping every 2 seconds consumes too many resources or can create some problems with internet connection.

        new Thread(() =>
        {
            if (CheckInternetConnection() == false)
            {
                Dispatcher.Invoke(new Action(delegate
                {
                    //internet access lost
                }));
            }
            else
            {
                Dispatcher.Invoke(new Action(delegate
                {
                    //internet access
                }));
            }

            Thread.Sleep(2000);
        }).Start();
    [DllImport("wininet.dll")]
    private extern static bool InternetGetConnectedState(out int Description, int ReservedValue);
    public static bool CheckInternetConnection()
    {
        int output = 0;
        return InternetGetConnectedState(out output, 0);
    }

These are two events that don't work in all occasions (only when IP or network card changes)

NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged
NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;

Can someone help me ?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Marius DV
  • 153
  • 2
  • 3
  • 9
  • Possible duplicate of [What is the best way to check for Internet connectivity using .NET?](https://stackoverflow.com/questions/2031824/what-is-the-best-way-to-check-for-internet-connectivity-using-net) – codeMonkey Dec 28 '17 at 00:10
  • As stated, your question is too broad. You complain that _"pinging every 2 seconds consumes too many resources"_ but you don't explain what resources are being consumed that are "too many", nor why you have to check every two seconds (as opposed to a longer interval), nor why you would expect some other approach to consume fewer resources. – Peter Duniho Dec 28 '17 at 00:17
  • Note that `NetworkChange.NetworkAvailabilityChanged` works fine, but there are a couple of caveats: **1)** it doesn't tell you if you have Internet access, it just tells you whether there's at least one non-loopback network adapter working, and **2)** there are often extra network adapters installed for various reasons that leave the system in a "network is available" state, even when your main Internet-connected adapter is disabled/unavailable. – Peter Duniho Dec 28 '17 at 00:17
  • Check out this its very fast method https://stackoverflow.com/a/25779403/8518037 – Vikas Sharma Jun 27 '19 at 19:16

3 Answers3

4

Note : In regaurds to your original solution

NetworkChange.NetworkAvailabilityChanged works fine, but there are a couple of caveats: 1) it doesn't tell you if you have Internet access, it just tells you whether there's at least one non-loopback network adapter working, and 2) there are often extra network adapters installed for various reasons that leave the system in a "network is available" state, even when your main Internet-connected adapter is disabled/unavailable - thanks to Peter Duniho

Since networking is more than just your routers or network card, and is really every hop to where ever it is you are trying to connect to at any time. The easiest and most reliable way is just ping a well known source like google, or use some sort of heart beat to one of your internet services.

The reasons this is the only reliable way is that any number of connectivity issues can occur in between you and the outside world. Even major service providers can go down.

So an IMCP ping to a known server like Google, or calling OpenRead on a WebClient are 2 valid approaches. These calls are not expensive comparatively and can be put into a light weight timer or continual task.

As for your comments you can probably signal a custom event to denote the loss of network after a certain amount of fails to be safe

To answer your question

But I fear that ping every 2 seconds consumes too many resources or can create some problems with internet connection.

Both methods are very inexpensive in regards to CPU and network traffic, any resources used should be very minimal

Note : Just make sure you are pinging or connecting to a server with high availability, this will allow such shenanigans and not just block you

Ping Example

using System.Net.NetworkInformation;

// Implementation 
using (var ping = new Ping())
{
   var reply = ping.Send("www.google.com");
   if (reply != null && reply.Status != IPStatus.Success)
   {
      // Raise an event
      // you might want to check for consistent failures 
      // before signalling a the Internet is down
   }
}

// Or if you wanted to get fancy ping multiple sources
private async Task<List<PingReply>> PingAsync(List<string> listOfIPs)
{
    Ping pingSender = new Ping();
    var tasks = listOfIPs.Select(ip => pingSender.SendPingAsync(ip, 2000));
    var results = await Task.WhenAll(tasks);

    return results.ToList();
}

Connection Example

using System.Net; 

// Implementation 
try
{
    using (WebClient client = new WebClient())
    {
       using (client.OpenRead("http://www.google.com/"))
       {
          // success
       }
    }
}
catch
{
    // Raise an event
    // you might want to check for consistent failures 
    // before signalling the Internet is down
}

Note : Both these methods have an async variant that will return a Task and can be awaited for an Asynchronous programming pattern better suited for IO bound tasks

Resources

Ping.Send Method

Ping.SendAsync Method

WebClient.OpenRead Method

WebClient.OpenReadAsync Method

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • _"its [sic] not expensive"_ -- since you don't know what the OP considers "expensive" (the solution they are using now shouldn't really have that much overhead), how can you say that sending a ping isn't expensive? And of course, when you write "ping", what do you really mean? IMCP? Checking for a URL at an HTTP server? Something else? Your answer is vague and hardly seems like it would help the OP in any case, given the specificity of their question. – Peter Duniho Dec 28 '17 at 00:19
  • I need an event for internet connection or disconnection. – Marius DV Dec 28 '17 at 00:21
  • @PeterDuniho all valid points, i thought this question was going to die in the SO Grave yard so i didn't put much work in to it – TheGeneral Dec 28 '17 at 00:21
  • It seems to me that when you see a question likely to "die in the SO Grave yard", there's generally a good reason for that, and you shouldn't put _any_ effort into it at all. Don't post an answer unless you know your answer is going to help, and unless you're willing to put enough effort into it to make it a _good_ answer. If you want to make any effort at all, put your effort into getting the question to a point where a good answer _can_ be provided. – Peter Duniho Dec 28 '17 at 00:22
1

NetworkInterface.GetIsNetworkAvailable() is unreliable... since it would return true even if all the networks are not connected to internet. The best approach to check for connectivity, in my opinion, is to ping a well known and fast online resource. For example:

public static Boolean InternetAvailable()
{
    try
    {
        using (WebClient client = new WebClient())
        {
            using (client.OpenRead("http://www.google.com/"))
            {
                return true;
            }
        }
    }
    catch
    {
        return false;
    }
}

Anyway, those two events you are subscribing don't work the way you think... actually they check for the hardware status of your network adapters... not whether they are connected to internet or not. They have the same drawback as NetworkInterface.GetIsNetworkAvailable(). Keep on checking for connectivity into a separate thread that pings a safe source and act accordingly. Your Interop solution is excellent too.

Tommaso Belluzzo
  • 23,232
  • 8
  • 74
  • 98
-1

Doing ping to public resources brings extra calls to your app and adds a dependency on that website or whatever you would use in the loop.

What if you use this method: NetworkInterface.GetIsNetworkAvailable() ? Would it be enough for your app's purposes?

I found it here https://learn.microsoft.com/en-us/dotnet/api/system.net.networkinformation.networkinterface.getisnetworkavailable?view=netframework-4.7.1#System_Net_NetworkInformation_NetworkInterface_GetIsNetworkAvailable

Andy
  • 523
  • 2
  • 13
  • This answer has been specifically ruled out by the OP. They complain that `NetworkChange.NetworkAvailabilityChanged` doesn't work for them, presumably because they have some ancillary network adapter not related to their Internet access, but which remains available even when the Internet goes down. The method you suggest above just returns the same information (though in a less efficient way, because you have to poll it instead of subscribing to an event). – Peter Duniho Dec 28 '17 at 00:21
  • Then having ping in an interval would be better. Besides that, I think it would be better to setup own service that you can ping by specific hostname. – Andy Dec 28 '17 at 00:26
  • The problem with this option is that NetworkInterface.GetIsNetworkAvailable() would be true even when the network is not connected to the internet. – Tommaso Belluzzo Dec 28 '17 at 00:44
  • @TommasoBelluzzo I think you did not read my previous comment :( – Andy Dec 30 '17 at 00:29