【发布时间】:2014-10-08 07:44:21
【问题描述】:
我正在尝试使用 AFURLSessionManager 在后台将大约 100 个图像上传到 S3,就像这里正在做的那样,小批量 10 个 - Manage the number of active tasks in a background NSURLSession
我正在使用共享的 NSURLSession 并在完成某些任务时根据更多任务添加任务。每个文件的平均大小约为 1.6 MB,每个任务队列保证运行的任务数为 5
这是我添加任务的方法: (也可作为更易于阅读的gist)
- (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 的 cmets 之后,我从 AFURLSessionManager 切换回 NSURLSession,因为正如他所指出的,使用基于块的回调对于 NSURLSession 来说是一项极具风险的业务。此外,我还使用了 HTTPMaximumConnectionsPerHost 并将其设置为 10 左右——这给出了更好的结果,但与我想要的结果相去甚远。
【问题讨论】:
-
没有太多的时间来查看你的代码,但有几件事需要检查: 1) 你是否在你的 NSURLSessionConfiguration 中设置了 HTTPMaximumConnectionsPerHost?使用它来设置任务队列的“宽度”。 2) 您是否使用 uploadTaskWithRequest 将所有这些请求/任务添加到同一个 NSURLSession?
-
1) 我已将 HTTPMaximumConnectionsPerHost 设置为 1。我拥有的任务队列一次运行 5 到 9 个任务。那么是否希望我将其设置为围绕这些值? 2)我正在使用单个共享的 AFURLSessionmanager 实例来添加任务..
-
我把你的代码写成一个要点,这样更容易阅读,在这里:gist.github.com/claybridges/8ca22217830e0ce1a0f1。
标签: ios amazon-s3 afnetworking nsurlsession nsurlsessionuploadtask