Monotouch:WebRequest连接在iPhone上关闭飞行模式后失败

Monotouch:WebRequest连接在iPhone上关闭飞行模式后失败,iphone,xamarin.ios,webrequest,Iphone,Xamarin.ios,Webrequest,我的monotouch应用程序正在与web服务进行定期后台同步。它运行良好,能够正确检测飞机模式。当我关闭WiFi时,它会自动开始使用WWAN(GPRS、3G)连接。到目前为止我很满意,但是。。。关闭Airplan模式后,如果没有可用的WiFi,我的应用程序将无法重新连接 它使用NetworkReachability对象正确检测WWAN是否可用以及是否需要连接。但是第一次尝试超时(90秒后,我使用计时器中止正在运行的请求)。当我再次尝试时,只要调用EndGetRequestStream,我就会得

我的monotouch应用程序正在与web服务进行定期后台同步。它运行良好,能够正确检测飞机模式。当我关闭WiFi时,它会自动开始使用WWAN(GPRS、3G)连接。到目前为止我很满意,但是。。。关闭Airplan模式后,如果没有可用的WiFi,我的应用程序将无法重新连接

它使用NetworkReachability对象正确检测WWAN是否可用以及是否需要连接。但是第一次尝试超时(90秒后,我使用计时器中止正在运行的请求)。当我再次尝试时,只要调用EndGetRequestStream,我就会得到一个WebException“Error:ConnectionFailure(没有到主机的路由)”。重新连接的唯一方法是启动另一个应用程序,如Mail,它可以建立连接。之后,我的应用程序再次完美连接。或者等待几分钟直到iPhone进入睡眠状态。唤醒后,连接设置再次正常

我做错了什么

下面的代码是使用ThreadPool.QueueUserWorkItem(CreateRequest)启动的

//
///同步步骤1:创建请求并开始异步发送数据。
/// 
私有void CreateRequest(对象状态)
{
尝试
{
Console.WriteLine(“第1阶段开始…”);
如果(!IsNetworkAvailable())
{
就绪(SyncState.NoConnection);
返回;
}
UIApplication.SharedApplication.NetworkActivityIndicatorVisible=true;
_request=(HttpWebRequest)WebRequest.Create(SyncUrl);
_request.Method=HttpMethodPost;
_request.ContentType=HttpContentTypeJson;
Console.WriteLine(“第2阶段正在启动…”);
_BeginGetRequestStream(新的AsyncCallback(StartRequest),null);
}
捕获(WebE例外)
{
Console.WriteLine(“WebException:+e.Message+”\r\n状态:+e.Status);
就绪(SyncState.ConnectionError);
}
}
/// 
///同步步骤2:从数据库读取同步数据并发送到服务器。
///开始异步获取响应。
/// 
私有void StartRequest(IAsyncResult asyncResult)
{
Console.WriteLine(“第2阶段已开始…”);
尝试
{
使用(var stream=_request.EndGetRequestStream(asyncResult))
{
使用(var textStream=newstreamwriter(stream))
{
Database.Instance.CreateSyncData().Save(textStream);
}
}
Console.WriteLine(“第3阶段正在启动…”);
_BeginGetResponse(新的AsyncCallback(ProcessResponse),null);
}
捕获(WebE例外)
{
Console.WriteLine(“WebException:+e.Message+”\r\n状态:+e.Status);
就绪(SyncState.ConnectionError);
}
}
/// 
///同步步骤3:获取响应和流程。
/// 
私有void ProcessResponse(IAsyncResult asyncResult)
{
Console.WriteLine(“第3阶段已开始…”);
尝试
{
使用(HttpWebResponse=(HttpWebResponse)\ u request.EndGetResponse(asyncResult))
{
使用(var textStream=newstreamreader(response.GetResponseStream()))
{
var data=(JsonObject)JsonObject.Load(textStream);
Database.Instance.ProcessSyncReply(数据);
Console.WriteLine(“成功:+data.ToString());
LastSyncTime=DateTime.Now;
就绪(SyncState.Synchronized);
}
}
}
捕获(WebE例外)
{
Console.WriteLine(“WebException:+e.Message+”\r\n状态:+e.Status);
就绪(SyncState.ConnectionError);
}
}
专用bool网络可用(需要外bool连接,仅外bool WAN)
{
布尔弗拉格萨瓦利;
NetworkReachabilityFlags NetworkReachabilityFlags=(NetworkReachabilityFlags)0;
使用(var networkReachability=新的networkReachability(主机名))
{
flagsAvailable=networkReachability.TryGetFlags(OutNetworkReachabilityFlags);
}
connectionRequired=0!=(networkReachabilityFlags&networkReachabilityFlags.connectionRequired);
onlyWWAN=0!=(networkReachabilityFlags&networkReachabilityFlags.IsWWAN);
返回flagsAvailable&&0!=(networkReachabilityFlags&networkReachabilityFlags.Reachable);
}
私有bool IsNetworkAvailable()
{
需要布尔连接;
布尔昂立湾;
bool available=IsNetworkAvailable(需要外部连接,仅外部WAN);
string status=“网络状态:”;
如果(!可用)
状态+=“不可用”;
其他的
{
状态+=“可用;”;
if(仅限广域网)
状态+=“移动;”;
如果(需要连接)
状态+=“需要连接”;
}
控制台写入线(状态);
返回可用;
}

处理网络事务的MonoTouch高级对象(ftp、smtp、http)利用BSD套接字。苹果有一种机制,即使3G/EDGE连接处于“活动”状态,它也会进入睡眠状态。唤醒此连接的唯一方法是使用CFStream或NSStream资源,没有公开的API来唤醒BSD套接字的GPRS连接。谢天谢地,你可以解决这个问题。MonoTouch提供了一个API:

MonoTouch.ObjCRuntime.Runtime.StartWWAN (Uri uri);

此api仅接受HTTP/HTTPs uri,并将快速连接到指定的api以重新唤醒所有连接的WWAN,此时WWAN将保持活动状态,直到空中计划或再次超时。

谢谢Geoff,这很有帮助。然而,第一次我大部分时间都会超时。重试
MonoTouch.ObjCRuntime.Runtime.StartWWAN (Uri uri);