我已经在应用程序中成功实现了NSOperationQueue。
我有一个操作队列,可能有1000个NSOperations,如下所示。
@interface Operations : NSOperation
@end
@implementation Operations
- (void)main
{
NSURL *url = [NSURL URLWithString:@"Your URL Here"];
NSString *contentType = @"application/json";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
NSError *err = nil;
NSData *body = [NSJSONSerialization dataWithJSONObject:postVars options:NSJSONWritingPrettyPrinted error:&err];
[request setHTTPBody:body];
[request addValue:[NSString stringWithFormat:@"%lu", (unsigned long)body.length] forHTTPHeaderField: @"Content-Length"];
[request setTimeoutInterval:60];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *resData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
}
@end
现在,对于该队列,我一次添加所有1000个操作。 我添加如下操作。
Operations *operation = [[Operations alloc]init];
[downloadQueue addOperation:operation];
现在时间间隔为60 [request setTimeoutInterval:60]
所以想想60秒后如果1000次操作中的300次操作完成,那么其他700次操作就会抛出请求超时错误。
那么在这种情况下我应该怎么做。
我可以恢复失败的操作吗?或者我应该再次进行操作并将其添加到队列中。
有没有比这个更好的机制?
答案 0 :(得分:3)
我最初的倾向是,是的,只是为超时请求创建新操作并将其重新投入队列。它只是感觉更简单,因为您已经有了为您的请求添加这些操作的逻辑。但是:
小心不要陷入无限循环。如果其中任何一个因任何原因而无限期失败,那么你的队列将会继续发挥作用。我保留了失败次数,以便您知道在经过一些有限次的尝试后停止重试请求。
如果您知道大量数据总是会失败,请考虑以某种方式对它们进行批处理。一种选择是依赖链。例如。您可以尝试添加200个操作,一个"等待" NSOperation,下一个200,另一个"等待" NSOperation,另一个"等待" op等。使第一个等待操作依赖于前200个请求。然后使下一个200依赖于第一个等待操作,依此类推:
基本上就像2而不是"等待"操作,完成"完成"运。假设您有一组1000个要发送的请求:将200个放入队列,然后完成"完成" op取决于那些200.当"完成"运行(根据定义,在完成那些200之后),然后它可以从阵列中拉出下一个200并将它们扔进去(加上一个新的"完成" op)。
(甚至可以考虑等待/完成操作"暂停"几秒钟让服务器喘息)
换句话说,对于#2和#3,我说'#34;立即爆炸200,等待,然后爆炸下一个200,等待等等。" (对我来说,200是任意的,你比我更了解你的情况最佳数字)
答案 1 :(得分:2)
您可以实现NSURLConnectionDelegate
方法connection:didFailWithError:
来检查同步请求是否失败,以及错误是否是请求超时。然后在委托回调中重试连接。
我应该注意到Apple强烈鼓励使用NSURLSession
而不是NSURLConnection
,因为NSURLConnection
中的许多方法现已弃用。
答案 2 :(得分:2)
第一点是 - 不要让它们全部同时运行!如果您尝试同时运行10个请求,则可以轻松地泛洪移动数据连接。因此,在其他任何事情之前,将队列的maxConcurrentOperationCount
设置为类似5。
仅这一点可能会大大减少您的问题,您可能不需要做任何其他事情。
您还应该真正考虑使用NSURLSession
,这样您还可以查看删除操作队列并使用HTTPMaximumConnectionsPerHost
来控制同时发出的请求数。
如果你仍然失败,那么其他答案之一的“递归类型”选项之一是一个可行的解决方案。我将向操作子类添加一个尝试计数,以便于跟踪,如果失败,则检查它失败的次数,并决定是否创建操作的新副本并将其添加到队列或发出警报