在同步调用上强制 NSUrlConnection 超时

Posted

技术标签:

【中文标题】在同步调用上强制 NSUrlConnection 超时【英文标题】:forcing NSUrlConnection timeout on a synchronous call 【发布时间】:2011-03-01 23:12:47 【问题描述】:

我知道有关 ios 上的 nsurlconnection 的讨论,并且至少有 240 秒的超时时间。我的问题是,如果我通过 NSURLConnection 的 + (NSData *)sendSynchronousRequest:(NSURLRequest )request returnedResponse:(NSURLResponse *)response error:(NSError **)error 发送同步调用,有没有我有机会在 240 秒结束之前取消吗?我在想也许设置一个计时器来取消这个同步请求,但我什至不确定它是否可能?我在想:

[self performSelector:@selector(cancelRequest:) withObject:myRequest afterDelay:myTimeOut];

我有一种感觉,如果请求以某种方式被释放,这将导致灾难,我无法确定这一点。想法?有没有人尝试过这样做?这是一个同步调用。

【问题讨论】:

对于任何在这里寻找解决方案的人,我有一个暂定的解决方案。这是你可以做的:创建一个计时器并确保你为 NSRunLoopModeCommon 安排它。然后创建您的 NSURLConnection 并将其安排在上述运行循环模式中。当连接返回或计时器触发时,设置一个标志。你的繁忙循环应该抓住这个并退出。请注意,在此过程中至少有一个线程会忙于旋转,因此您必须确保该线程不是主线程。当我有更多时间时,我会发布一个代码示例。调度运行循环对于这个工作非常重要! 这个不能工作。首先,您不能为任何运行循环安排同步请求,您只能使用异步请求来执行此操作;同步请求只是阻止任何线程进行调用——它是一个类方法,而不是一个实例方法。其次,NSURLRequest 甚至不响应诸如 cancelRequest: 之类的东西。你不能向 NSURLRequest 发送任何类型的取消消息,你的应用只会崩溃。 嗯,它并没有取消 NSURLRequest ——也许我应该更明确地说明这一点。它正在取消一个 NSURLConnection。我并不是说连接应该是同步的,只是从调用者的角度来看它看起来是同步的。这意味着发出异步请求、阻塞线程并从另一个线程取消。这还不可能吗? 这不是不可能的,但是没有理由阻塞线程。只需在调用之前分解代码以执行您需要的任何操作,进行异步调用,然后在完成后执行您需要的任何操作。从这个角度来看,您可以轻松取消它。如果需要阻塞用户界面,可以使用屏蔽视图和微调器什么的,但不要阻塞线程。 即使这样做,你也绝对不能调用 +sendSynchronousRequest:returningResponse:error: -- 如果你调用那个方法,你不能取消它,不管你尝试什么. 【参考方案1】:

您无法取消它。只需不要使用它,而是使用异步调用。那些您可以轻松取消的。

【讨论】:

@Ying:您的问题没有没有得到解答。你根本不喜欢这个答案。您不能取消同步请求。如果你希望你的 NSURLConnection 是可中断的,你必须使它成为一个异步请求。然后,您可以随时取消它。你上面的建议会失败。 @Ying:我同意 Jason Coco 的观点。您问是否可能;答案是。如果你想取消一个请求,你必须使用异步调用。【参考方案2】:

这似乎对我有用:

NSURL *url = [NSURL URLWithString:@"http://someurl.com"];
NSURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5];
NSHTTPURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
if (response == nil) 
    // timed out or failed
 else 
    // all good

当然将超时间隔设置为你希望它在超时之前阻塞主线程的时间 - 上面的代码在 5 秒后成功超时

在 iOS6 和 iOS5.1 中测试

【讨论】:

你的意思是“阻塞调用线程”。您不必在主线程上调用sendSynchronousRequest【参考方案3】:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url    cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];

webData = (NSMutableData *)[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];

if (webData==nil) 
        [self displayAlert:@"Time Out" message:@"Request Timed Out"];
    

正好在 10 秒内超时。

【讨论】:

感谢它的帮助!

以上是关于在同步调用上强制 NSUrlConnection 超时的主要内容,如果未能解决你的问题,请参考以下文章

如何强制内联 div 保持在同一行?

强制解开已在同一行代码中选择性访问的变量是不是安全?

如何强制 ListView 在同一行中显示来自 ObservableCollection 不同元素的两个不同数据

如何在NSURLConnection中禁用keepalive?

第三十一篇iOS 9版本适配

(C/C++) 在同一行初始化并返回数组