当我多线程[NSString stringWithContentsOfURL:someURL]时,为什么我会得到620错误;?

时间:2013-01-21 22:37:40

标签: grand-central-dispatch

以下是我正在使用的代码片段。 我有一个名为x_locator的模型。当我多线程化模型时,maps.google.com会返回620个错误(请求太多太快),但是当我将模型留在主线程上时,它工作正常...只有UI被锁定,而请求正在进行

-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr {
    NSString *urlStr = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?    q=%@&output=csv", 
                       [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSString *locationStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlStr]];
    NSArray *items = [locationStr componentsSeparatedByString:@","];

    double lat = 0.0;
    double lon = 0.0;

    if([items count] >= 4 && [[items objectAtIndex:0] isEqualToString:@"200"]) {
        lat = [[items objectAtIndex:2] doubleValue];
        lon = [[items objectAtIndex:3] doubleValue];
    }
    else {
        NSLog(@"Address, %@ not found: Error %@",addressStr, [items objectAtIndex:0]);
    }
    CLLocationCoordinate2D location;
    location.latitude = lat;
    location.longitude = lon;

    return location;
}

编辑:以下是我尝试使用GCD的方法......这是我的ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    //set any delegates
    self.locationManager.delegate = self;
    [locationManager startUpdatingLocation];
    fuelMapView.showsUserLocation = YES;

    [self setInitialRegion];
    locationManager.distanceFilter = 100;

    //create the model
    x_locator = [[Locator alloc]init];
    x_locator.delegate = self;

    dispatch_queue_t finder = dispatch_queue_create("Locator", NULL);
    //if I do this, only some of the locations are found. If I leave it on the main thread, all locations are found.
    dispatch_async(finder, ^{
    [x_locator getUsersZipUsingLocation:[locationManager location]];
     });
}

所有getUsersZipUsingLocation:所做的是使用反向地理编码获取用户邮政编码,然后调用另一个检索地址数组的方法(根据用户zip),最后将每个地址转换为坐标使用-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr

的位置

编辑2: 由于人们可能会失去问题的焦点并继续判断我的编码的优雅,我非常犹豫是否完整地发布代码....

无论如何......在我调用方法-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr之前,我必须将地址组合成一个我可以作为变量addressStr传递的形式。地址分成几部分,所以我组装了各个部分然后继续从网址中获取数据......

NSString *urlStr = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv",
                    [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

返回数据后,我说[NSThread sleepForTimeInterval:0.05];并接下来的请求。

感谢您的评论和时间:)

1 个答案:

答案 0 :(得分:2)

首先,getLocationFromAddressString:不应以get为前缀;尝试downloadretrieve或只是省略它(约定)。

其次,发布有关如何实际进行并发呼叫的详细信息。你有多少请求?

“太多请求太快”听起来很精确;你需要限制在远程服务器上抛出请求的速度。

我过去曾使用信号量来限制并发性。

Grand Central Strategy for Opening Multiple Files


  

所有getUsersZipUsingLocation:确实是使用用户邮政编码   反向地理编码,然后它调用另一个检索   地址数组(根据用户zip),最后是每个地址   这些地址使用转换为坐标位置    - (CLLocationCoordinate2D)getLocationFromAddressString:(NSString *)addressStr

通过以下方式调用:

dispatch_async(finder, ^{
[x_locator getUsersZipUsingLocation:[locationManager location]];
 });

首先,您现在有一个异步调用来加载该信息。因此,毫不奇怪,只找到了“一些”物品。一旦你转向异步,你必须使用某种通知机制来指示加载何时完成

假设usersZipUsingLocation:是同步的,您可以:

dispatch_async(finder, ^{
[x_locator getUsersZipUsingLocation:[locationManager location]];
[self yoManILoadedTheGoodsDealWithTheUpdate];
 });

但这仍然没有解释你的620.那620表示你同时(或几乎如此)发出一堆请求。上述任何一项都没有声称的50毫秒延迟。

所以...这个故事似乎还有更多! :)


仍然不清楚为什么要达到API请求限制。

你真的不应该使用睡眠机制来推迟这些事情。相反,如果绝对必要,使用信号量模式的组合来控制飞行请求中的同时#(最好使用系统的异步加载API)和基于计时器的延迟。这会将所有延迟相关的东西推送到系统而没有保证的线程合同(根据睡眠线程的要求)。