1

我正在尝试使用 AFURLSessionManager 在后台将大约 100 张图像上传到 S3,小批量 10 个,就像这里正在做的那样 -管理后台 NSURLSession 中的活动任务的数量

我正在使用共享的 NSURLSession 并在完成某些任务时根据更多任务添加任务。每个文件的平均大小约为 1.6 MB,每个任务队列保证运行的任务数为 5

这是我添加任务的方法:(也可作为更易于阅读的要点

    - (void) addTasksToSessionWithTaskObject:(Task*)taskObject withSessionInitialisationNeeded:(BOOL) needed{

        NSString *filePath = [[NSBundle mainBundle] pathForResource:pathForResourceFile ofType:resourceFileType];
        S3PutObjectRequest *putObjectRequest = [[S3PutObjectRequest alloc] initWithKey:targetFileKey
                                                                              inBucket:_bucketname];
        putObjectRequest.cannedACL = [S3CannedACL publicReadWrite];
        putObjectRequest.filename = filePath;
        putObjectRequest.contentType = [resourceFileType isEqualToString:@"MOV"] ? @"movie/mov" : @"image/jpg";
        putObjectRequest.endpoint = @"http://s3.amazonaws.com";
        putObjectRequest.contentLength=[[[NSFileManager defaultManager]
                                         attributesOfItemAtPath:filePath error:nil] fileSize];
        putObjectRequest.delegate = self;
        [putObjectRequest configureURLRequest];
        NSMutableURLRequest *request = [s3Client signS3Request:putObjectRequest];
        NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://s3.amazonaws.com/UploadTest/%@",taskObject.fileKey]]];

        [request2 setHTTPMethod:request.HTTPMethod];
        [request2 setAllHTTPHeaderFields:[request allHTTPHeaderFields]];

        if(needed) {

                sharedSession = [self backgroundSession];   
        }
   NSURLSessionUploadTask *task = [sharedSession uploadTaskWithRequest:request2           fromFile:forFileUrl];

    task.taskDescription = pathForResourceFile;
    [currentlyActiveTaskIdArray addObject:@([task taskIdentifier])];

    [task resume];
}

这就是我对代表所做的

- (void)URLSession:(NSURLSession *)sessionI task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error{

    dispatch_async(dispatch_get_main_queue(), ^{

        __block UIBackgroundTaskIdentifier bgTaskI = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:bgTaskI];
        }];

        if([currentlyActiveTaskIdArray containsObject:@([task taskIdentifier])]){
            [currentlyActiveTaskIdArray removeObject:@([task taskIdentifier])];
        }
        if(currentlyActiveTaskIdArray.count < LOWER_SLAB_FOR_TASKS + 1){   
            [self initiateS3UploadForSetOfTasksIsItBeginningOfUpload:NO];
        }
        [[UIApplication sharedApplication] endBackgroundTask:bgTaskI];
    }); 
}

这是添加更多任务的代码

 - (void) initiateS3UploadForSetOfTasksIsItBeginningOfUpload:(BOOL)beginning{
        int i=0;
        for(Task *eachTaskObject in tasksArray){
            if(i < numberOfTasksTobeAdded){  
                [self addTasksToSessionWithTaskObject:eachTaskObject WithSessionInitialisationNeeded:NO];
                i++;
            }
        }
    }

我一直在前台模式和后台模式下运行 100 个文件的测试。在Foreground模式下,文件以一致、稳定、恒定的速度上传,前3分钟完成90个文件,其余10个文件在20秒内完成。

当我在后台模式下运行应用程序时,我希望它上传前 90 个文件的速度与在 3 分钟的前台窗口中一样快,然后放慢速度……但事实并非如此。在后台模式下,它会在第一分钟上传 15 个文件,然后开始减速……很多。它以越来越慢的间隔开始上传 8 个文件批次:1 分钟、3 分钟、5 分钟、10 分钟,现在是 17 分钟。我们在 46 分钟内有 65 个文件。

有没有办法让它保持快速至少拳头 3 分钟,或者在后台保持一致的速度?

更新:根据 Clay 的评论,我从 AFURLSessionManager 切换回 NSURLSession,因为正如他所指出的,使用基于块的回调是 NSURLSession 的一项极具风险的业务。此外,我还使用了 HTTPMaximumConnectionsPerHost 并将其设置为 10 左右——这给出了更好的结果,但与我想要的结果相去甚远。

4

1 回答 1

2

据我所知,setTaskDidCompleteBlock:不是 Apple API相关的NSURLSession方法。这一种AFURLSessionManager方法(文档)。如果您在此使用 AFNetworking,那么您需要宣布粗体、顶部、正面和中心。这使用NSURLSession. 我猜 AFNetworking 的基于背景NSURLSession的实现有它自己的弱点和特质。

就我而言,无论我在持续后台NSURLSession上传方面取得了什么成功,都只使用了股票 API。


解决问题等

  • 关于 AFNetworking:我们将它用于一般的 web api I/O。在 NSURLSession 出来的时候,AFNetworking 确实没有强大的支持 app-in-background 操作,所以我没有使用它。也许是因为我经历了背景的痛苦和欺侮,我以“现在你有两个问题”NSURLSession的标题对 AFNetworking 的背景表示怀疑。但也许他们现在已经破解了坚果。

    • 我争取一个NSURLSession。我开始对会话的创建和销毁很随意,但发现这会导致一些真正棘手的问题。经验似乎在这方面有所不同。

    • 我使用默认的HTTPMaximumConnectionsPerHost,没有问题。Apple 文档对默认值保持沉默,但以下是 lldb 在我选择的随机特定设备/操作系统中告诉我的内容:
      (lldb) p [config HTTPMaximumConnectionsPerHost] (NSInteger) $0 = 4
      如果您在后台运行速度变慢时遇到问题,我怀疑调整是否在正确的轨道上。

    • FWIW, backgroundNSURLSession不支持块接口,只支持委托。

于 2014-08-15T01:56:04.103 回答