The monotouch mono application periodically synchronizes the background with the web service. It works great and correctly determines the flight mode. When I turn off WiFi, it automatically starts using WWAN connection (GPRS, 3G). So far I am very pleased, but ... After disabling Airplan mode, there is no way to connect to my application when Wi-Fi is not available.
It correctly detects using the NetworkReachability object accessible by WWAN and that a connection is required. But the first timeout attempt (after 90 seconds, I cancel the start request using the timer). When I try again, I get a WebException "Error: ConnectionFailure (no route to the host)" as soon as I call EndGetRequestStream. The only way to connect again is to start another application, such as Mail, which creates the connection. After that, my application connects flawlessly again. Or wait a few minutes until the iPhone falls asleep. After waking up, the connection is configured ok again.
What am I doing wrong?
The code below runs using ThreadPool.QueueUserWorkItem (CreateRequest);
private void CreateRequest(object state)
{
try
{
Console.WriteLine("Phase 1 started...");
if (!IsNetworkAvailable())
{
Ready(SyncState.NoConnection);
return;
}
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
_request = (HttpWebRequest)WebRequest.Create(SyncUrl);
_request.Method = HttpMethodPost;
_request.ContentType = HttpContentTypeJson;
Console.WriteLine("Phase 2 is starting...");
_request.BeginGetRequestStream(new AsyncCallback(StartRequest), null);
}
catch (WebException e)
{
Console.WriteLine("WebException: " + e.Message + "\r\nStatus: " + e.Status);
Ready(SyncState.ConnectionError);
}
}
private void StartRequest(IAsyncResult asyncResult)
{
Console.WriteLine("Phase 2 started...");
try
{
using (var stream = _request.EndGetRequestStream(asyncResult))
{
using (var textStream = new StreamWriter(stream))
{
Database.Instance.CreateSyncData().Save(textStream);
}
}
Console.WriteLine("Phase 3 is starting...");
_request.BeginGetResponse(new AsyncCallback(ProcessResponse), null);
}
catch (WebException e)
{
Console.WriteLine("WebException: " + e.Message + "\r\nStatus: " + e.Status);
Ready(SyncState.ConnectionError);
}
}
private void ProcessResponse(IAsyncResult asyncResult)
{
Console.WriteLine("Phase 3 started...");
try
{
using (HttpWebResponse response = (HttpWebResponse)_request.EndGetResponse(asyncResult))
{
using (var textStream = new StreamReader(response.GetResponseStream()))
{
var data = (JsonObject)JsonObject.Load(textStream);
Database.Instance.ProcessSyncReply(data);
Console.WriteLine("Success: " + data.ToString());
LastSyncTime = DateTime.Now;
Ready(SyncState.Synchronized);
}
}
}
catch (WebException e)
{
Console.WriteLine("WebException: " + e.Message + "\r\nStatus: " + e.Status);
Ready(SyncState.ConnectionError);
}
}
private bool IsNetworkAvailable(out bool connectionRequired, out bool onlyWWAN)
{
bool flagsAvailable;
NetworkReachabilityFlags networkReachabilityFlags = (NetworkReachabilityFlags)0;
using (var networkReachability = new NetworkReachability(HostName))
{
flagsAvailable = networkReachability.TryGetFlags(out networkReachabilityFlags);
}
connectionRequired = 0 != (networkReachabilityFlags & NetworkReachabilityFlags.ConnectionRequired);
onlyWWAN = 0 != (networkReachabilityFlags & NetworkReachabilityFlags.IsWWAN);
return flagsAvailable && 0 != (networkReachabilityFlags & NetworkReachabilityFlags.Reachable);
}
private bool IsNetworkAvailable()
{
bool connectionRequired;
bool onlyWWAN;
bool available = IsNetworkAvailable(out connectionRequired, out onlyWWAN);
string status = "Network status: ";
if (!available)
status += "Not available";
else
{
status += "Available; ";
if (onlyWWAN)
status += "Mobile; ";
if (connectionRequired)
status += "Connection required";
}
Console.WriteLine(status);
return available;
}
source
share