在使用NSURLSession在后台上传文件时无法保持恒定速度

我试图在AFURLSessionManager的背景下以小批量10的方式上传一些100图像到S3中,就像这里正在做的事情一样 – 在后台pipe理活动任务的数量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个文件的testing。 在前台模式下,文件以一致,稳定,匀速上传,前3分钟完成90个文件,20秒完成剩余的10个文件。

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

有没有办法保持至less拳头3分钟的速度,或保持一致的速度在后台?

更新:继Clay的评论之后,Ive从AFURLSessionManager切换回NSURLSession,因为他指出使用基于块的callback是一个NSURLSession风险极高的业务。 进一步,我已经玩了HTTPMaximumConnectionsPerHost并设置这个10左右 – 这给了更好的结果,但远不及我想要的东西。

从我可以告诉, setTaskDidCompleteBlock:不是一个Apple API, NSURLSession相关的方法。 这一个AFURLSessionManager方法( docs )。 如果您正在使用AFNetworking,那么您需要宣布粗体 ,顶部,正面和中心。 这与使用NSURLSession完全一样。 我想AFNetworking的背景基于NSURLSession的实现有它自己的弱点和特质。

就我而言,无论成功的持续背景NSURLSession上传只使用股票API。


解决问题等

  • 关于AFNetworking:我们用它来做一般的web api I / O。 在NSURLSession出来的时候,AFNetworking并没有强有力地支持app-in-background操作,所以我没有使用它。 也许是因为我经历了背景NSURLSession痛苦和NSURLSession ,我在“现在你有两个问题”的标题下看着AFNetworking背景。 但也许他们现在已经破解了这个螺母。

    • 我争取一个NSURLSession 。 我开始讨论会议的创build和破坏,但是发现这是为了一些真正的难题。 这方面的经验似乎有所不同。

    • 我使用默认的HTTPMaximumConnectionsPerHost ,没有问题。 苹果文档对默认值是无声的,但是这里是lldb在我select的随机特定设备/操作系统中告诉我的:
      (lldb) p [config HTTPMaximumConnectionsPerHost] (NSInteger) $0 = 4
      如果你在背景减速方面遇到麻烦,我怀疑是否在正确的轨道上调整。

    • FWIW,后台NSURLSession不支持块接口,只能委托。