首页 > 解决方案 > NSURLSessionDataTask 的最大并发实例数

问题描述

我有一个调用 API 的函数,NSURLSessionDataTask你可以在这里看到它:

- (void)getExplorerUrl:(void (^)(NSString *))measurement_url {
    NSString *path = [NSString stringWithFormat:@"https://api.ooni.io/api/v1/measurements?report_id=%@&input=%@", self.report_id, self.url_id.url];
    NSURL *url = [NSURL URLWithString:path];
    NSURLSessionDataTask *downloadTask = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
            NSArray *resultsArray = [dic objectForKey:@"results"];
            if ([resultsArray count] == 0)
                measurement_url(nil);
            measurement_url([[resultsArray objectAtIndex:0] objectForKey:@"measurement_url"]);
        }
        else {
            // Fail
            measurement_url(nil);
            NSLog(@"error : %@", error.description);
        }
    }];
    [downloadTask resume];
}

此函数使用完成处理程序在异步调用完成时返回一个值。

现在我想要一个 for 循环来循环许多对象并为每个对象调用这个 API:

    for (Measurement *measurement in [Measurement measurementsWithJson]){
        [measurement getExplorerUrl:^(NSString *measurement_url) {
            if (measurement_url != nil){
                //Do something
                NSLog(@"%@ measurement_url %@",measurement.Id, measurement_url);
            }
            else {
                NSLog(@"%@ measurement_url null", measurement.Id);
            }
        }];
    }

有没有办法将最大并发异步调用设置为 10?然后在一个呼叫完成后立即执行下一个呼叫。

标签: iosobjective-ccocoa-touch

解决方案


我同意@Rob 的观点,他可以为URLSession. 但是,如果这sharedSession用于不同的作业,并且他希望此作业在最大并发异步调用 10 的情况下运行,我建议使用其中一个NSOperationQueuedispatch_semaphore解决此问题。请参考以下示例以大致了解这些方法

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 10;

for (int i = 1; i <= 30; i++) {
    [queue addOperationWithBlock:^{
        NSLog(@"[Q] %d", i);
        sleep(1);
    }];
}

或者

dispatch_queue_t q = dispatch_queue_create("q.q", DISPATCH_QUEUE_CONCURRENT);
dispatch_semaphore_t s = dispatch_semaphore_create(10);
for (int i = 1; i <= 30; i++) {
    dispatch_async(q, ^{
        NSLog(@"[Q] %d", i);
        sleep(1);
        dispatch_semaphore_signal(s);
    });

}

您可以从控制台观察以查看结果。基本上这两种方法会同时执行最多 10 个调用,只要一个完成,其他的就会进入执行队列。

我希望这将帮助您解决您的问题。有需要可以讨论哦!!!


推荐阅读