We experience long blocking delay during attempts to call a web service when there is no network connectivity

• We are using .NETMF 4.1
• GHIElectronics.NETMF 4.17
• DPWS_V_4_1_7706_0
• WsHttp configured web services

When the network is not available and a web service call is attempted, The call blocks for an inordinate amount of time (~90 seconds) thus blocking all processing on the device and rendering it frozen. This is not acceptable behavior. It should honor a timeout or throw an exception in a much shorter period of time.

Users usually have a thread that handles sockets and if things went on for too long, the thread is terminated and restarted.

As I know this is problem in NETMF4.1 and will be fixed in NETMF4.2 You can temporary override it that you in other thread try open socket to IP 8.8.8.8. or some other public IP and in main thread check if you for example in 5 seconds succesfully connect make your DPWS request and if not then is something wrong with network and you terminate thread…
Other functions to check host like:

Dns.GetHostEntry("www.ghielectronics.com");

Will complete block your device…

That is a good idea, using UDP methods to probe the network availability.

Here is one quick example how I check network availablity without blocking whole device:
http://www.tinyclr.com/forum/23/6126/

Maybe there is some better and optimized way to do this but this is for now what work for me :slight_smile:

Wow great Dejan! Why not post this on codeshare too? :slight_smile: I am sure others will find this very useful.

Gus I will take some time and upload it on http://code.tinyclr.com and on forum under Codeshare :slight_smile:

Dejan,

This is very good, and I plan to use it in my current Cobra project, but I think I found one little bug:

I think the ‘&’ should be “&&”…


while (network_online_checking & time < _ping_timeout)
{
       Thread.Sleep(100);
        time += 100;
}

jasdev: for me normaly work with one & but I will change code to && :slight_smile: Build without warnings and also work in production :slight_smile:

I understand that… and in fact that is what I have done to probe the network prior to making the call. However, my point is that it shouldn’t be that way. There needs to be a way to set a timeout on the call of interest. What happens if the network probe call succeeds because the network was up but then in a split second between the probe call and the actual service call it goes down. This race condition is possible albeit not as likely… It begs the question then, should we spend all this effort creating workarounds or should we invest that time in making the networking stack more robust. If you run a similar test on .NET full you will see how the network behavior should be under these conditions.

As Im said this is not problem in GHI libraryes because EMX and ChipworkX use native .NETMF sockets. As I know this blockings are fixed In .NETMF 4.2 as users report… So you can use override as I use now or wait few months for .NETMF4.2 update.

Isn’t this the same on the big .NET?

Here is a simple illustration of .NET 4 Full network behavior

It loops ever 2 seconds and checks for the availability of a connection to “www.msn.com

If you then unplug the ethernet (or other network connection) it fails immediately and recovers gracefully.


using System;
using System.Threading;

namespace HttpRequestTimeout
{
    internal class Program
    {
        private static Thread netThread;
        private static readonly ManualResetEvent monitor = new ManualResetEvent(false);

        private static void Main()
        {
            while (true)
            {
                try
                {
                    monitor.Reset();
                    var checker = new NetCheck();
                    netThread = new Thread(checker.Start);

                    checker.NetResponse += (sender, eventArgs) =>
                    {
                        Console.WriteLine("Network is " + (eventArgs.IsNetworkAvailable ? "available" : "unavailable")  + " at: " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
                        monitor.Set();
                    };

                    Console.WriteLine("Network check started at: " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
                    netThread.Start();

                    if (!monitor.WaitOne(5000))
                        Console.WriteLine("Network timeout occurred at: " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
                }
                catch (Exception)
                {
                    monitor.Set(); Console.WriteLine("Network is unavailable: " + DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss"));
                }

                Thread.Sleep(2000);
            }
        }
    }

    public class NetCheck
    {
        public void Start()
        {
            try
            {
                var request = System.Net.WebRequest.Create("http://www.msn.com");
                var response = request.GetResponse();

                if (NetResponse != null)
                    NetResponse(this, new NetCheckArgs { IsNetworkAvailable = true });

                response.Close();
            }
            catch (Exception)
            {
                if (NetResponse != null)
                    NetResponse(this, new NetCheckArgs { IsNetworkAvailable = false });
            }
        }

        public event NetCheckHandler NetResponse;
    }

    public class NetCheckArgs : EventArgs
    {
        public bool IsNetworkAvailable { get; set; }
    }

    public delegate void NetCheckHandler(object sender, NetCheckArgs args);
}

Yes netmf doesn’t detect a cable disconnect and close sockets immediately. I think users normally handle this by terminating the thread handling the socket.

Only under some conditions. Unless you’re using TCP KeepAlive, there’s no way to know whether there’s a complete, functioning network between you and your destination except to try to use it (and that’s essentially what KeepAlive does, it sends packets back and forth every so often).

Sending a packet involves some wait to see if it was received. The reason it works better for you on the desktop is because the actual packet send fails when the network is unplugged, not because it has some magic way to know that there’s no connection.