NetCF application hanging when remote server disconnects from the network?

I've been seeing a few reports of NetCF web service applications hanging when the target server disconnects from the network. If you are experiencing this, I may have a solution for you.

What we have found is that if the server disconnects before sending the initial HTTP response to the client (maybe it never actually received the HTTP request, or failed just prior to sending the response), NetCF (v1 and v2 beta1) will wait indefinitely for the response to be received.

Many of you may note that there is a Timeout property on the SoapHttpClientProtocol class (the parent class of each of your web service client proxy classes). This timeout does not come into play here (it applies to individual reads and writes between the client and server after the client receives the initial server response -- it does not specify the maximum amount of time for the call to complete).

Please note that since mobile devices typically operate on slow connections, timing out the entire request would likely cause most, if not all web service calls to fail and that sometimes your application may look hung and then eventually, start responding again (if the server was just really slow in responding).

If you are encountering this issue, the following workaround may be helpful. Please note that while this code utilizes web services, the workaround applies equally to the HTTP client (HttpWebRequest). Also note that this code implements a timeout on the complete method call and the timer will need to wait long enough to receive all of the expected data from the server (I recommend a few minutes in most cases).

orignal code
MyService service = new MyService();
service.Method( /* args */ );

workaround code
System.Threading.Timer timer;
Int32 timeout = 60000;
MyService service = new MyService();

private void CallService()
{
try
{
// set the timeout to longer than you reasonably expect a user to wait for the call to complete
this.timeout = 600000; // NOTE: this is a really long timeout

        // create the timer
this.timer = new System.Threading.Timer(new TimerCallback(TimeoutHandler),
null,
0,
this.timeout);

        // call the web service method
this.service.Method( /* args */ );
}
catch(Exception e)
{
// dispose of the timer
this.timer.Dispose();

// handle failure
// TODO: perform any required cleanup and/or user notification, etc
}
}

private void TimeoutHandler(Object obj)
{
// we have waited long enough for the server to respond
// abort the call
this.service.Abort();
}

Hope this helps!
-- DK

Disclaimers:
This posting is provided "AS IS" with no warranties, and confers no rights.
Some of the information contained within this post may be in relation to beta software. Any and all details are subject to change.