head.WriteLine()

Samstag, Februar 16, 2008

Check for online/offline state correctly

With the introduction of the System.Net.NetworkInformation namespace in .NET 2.0, you can easily check for the availability of a network. When you want to be notified when the machine gets online or offline, you can add a handler to the NetworkChange.NetworkAvailabilityChanged event.

NetworkChange.NetworkAvailabilityChanged +=
delegate(object sender, NetworkAvailabilityEventArgs e)
{
    _isOnline = e.IsAvailable;
};

The problem with this event is, that it isn't triggerd if you have a loopback adapter installed on your machine.

But the NetworkChange class has a NetworkAddressChanged event, that is fired, when the IP-address of one of your network adapters changes. In the handler you can get the available adapters and check the type via the NetworkInterface.NetworkInterfaceType property. Additionally the Networkinterface class has a static LoopbackInterfaceIndex property that gives you the index of the loopback adapter. With that in mind you can implement an online/offline check like this:

NetworkChange.NetworkAddressChanged += delegate
{
  _isOnline = false;
  NetworkInterface[] adapters =
    NetworkInterface.GetAllNetworkInterfaces();
  for (int i = 0; i < adapters.Length; i++)
  {
    NetworkInterface adp = adapters[i];
    if (adp.OperationalStatus==OperationalStatus.Up &&
      adp.NetworkInterfaceType != 
      NetworkInterfaceType
.Loopback &&
      i + 1 != NetworkInterface.LoopbackInterfaceIndex)
    {
      _isOnline = true;
      break;
    }
  }
};

If you want to refresh your UI when the state changes, you must synchronize the threads, because the NetworkAddressChange event calls you from a worker thread. But thanks to the SynchronizationContext class introduced in .Net 2.0 you can easily do that like this: (thanks to Dominick for the hint):

class MyClass
{
 
SynchronizationContext _syncContext;

  public MyClass()
  {
    _syncContext = SynchronizationContext.Current;
  }

...

void MyMethod()
{
  ...
  _syncContext.Post(delegate
  {
    ToggleOnlineState(isOnline);
  }, null);
}

Now you get informed correctly if the machine moves online or offline.