我正在尝试使用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个文件,在20秒内完成剩余的10个文件。
当我在后台模式下运行应用程序时,我希望它能够像在3分钟的前景窗口中一样快地上传前90个文件,然后在那之后放慢速度......但事实并非如此。在后台模式下,它在第一分钟上传了15个文件,然后开始减速...很多。它开始以较慢和较慢的间隔分8个文件批量上传:1分钟,3分钟,5分钟,10分钟,现在17分钟。我们在46分钟内获得65个文件。
有没有办法让它至少在第3分钟保持快速,或者在后台保持一致的速度?
更新:在Clay的评论之后,我已经从AFURLSessionManager切换回NSURLSession,因为他指出使用基于块的回调是NSURLSession的极其危险的业务。此外,我已经使用了HTTPMaximumConnectionsPerHost并将其设置为10左右 - 这已经给出了更好的结果,但远不及我想要的那样。
答案 0 :(得分:2)
据我所知,setTaskDidCompleteBlock:
不是Apple API,NSURLSession
- 相关方法。 是 AFURLSessionManager
方法(docs)。如果您在此使用AFNetworking,则需要宣布粗体,顶部,正面和中间。这与使用NSURLSession
完全相同 。我猜想AFNetworking的基于NSURLSession
的后台实现有自己的缺点和特性。
就我而言,无论我在上传NSURLSession
次上传时取得的成功,都只使用了股票API。
关于AFNetworking:我们将它用于一般的web api I / O.在NSURLSession问世的时候,AFNetworking确实没有强大的支持app-in-back操作,所以我没有使用它。也许是因为我经历了背景NSURLSession
痛苦&amp;在“现在你有两个问题”的标题下,我对AFNetworking的背景感到怀疑。但也许他们现在已经破解了坚果。
我努力争取一个NSURLSession
。我开始对创作和骑士感到骄傲破坏会议,但发现这是一些真正的粗糙问题。经验似乎有所不同。
我使用默认的HTTPMaximumConnectionsPerHost
,没有问题。 Apple文档对默认值保持沉默,但这是lldb在我选择的随机特定设备/操作系统中告诉我的内容:
(lldb) p [config HTTPMaximumConnectionsPerHost]
(NSInteger) $0 = 4
如果你在后台运行速度变慢的情况下遇到麻烦,我怀疑调整是否在正确的轨道上。
FWIW,后台NSURLSession
不支持块接口,仅限委托。