1

ここで行われているように、AFURLSessionManager を使用してバックグラウンドで S3 に約 100 個の画像を 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 個のファイルを使用してテストを実行しています。フォアグラウンド モードでは、一貫した安定した一定の速度でファイルをアップロードし、最初の 3 分間で 90 個のファイルを完了し、残りの 10 個のファイルを 20 秒で完了します。

アプリをバックグラウンド モードで実行すると、最初の 90 個のファイルが 3 分間のフォアグラウンド ウィンドウと同じ速度でアップロードされ、その後速度が低下すると予想されますが、そうではありません。バックグラウンド モードでは、最初の 1 分間に 15 個のファイルをアップロードし、その後速度が低下し始めます。1 分、3 分、5 分、10 分、そして今は 17 分と、徐々に遅い間隔で 8 つのファイル バッチでアップロードを開始します。46 分で 65 ファイルになりました。

少なくとも最初の 3 分間は速度を維持するか、バックグラウンドで一定の速度を維持する方法はありますか?

更新:ここで Clay からのコメントに続いて、私は AFURLSessionManager から NSURLSession に切り替えました。なぜなら、彼が指摘するように、ブロックベースのコールバックを使用することは NSURLSession で非常に危険なビジネスだからです。さらに、私は HTTPMaximumConnectionsPerHost で遊んで、これを約 10 に設定しました。これにより、より良い結果が得られましたが、私が望むものにはほど遠いものでした。

4

1 に答える 1

2

私が知るsetTaskDidCompleteBlock:限り、これは Apple API にNSURLSession関連付けられたメソッドではありません。メソッドdocs)です。これに AFNetworking を使用している場合は、太字、上、前、中央をアナウンスする必要があります。それは、 を使用するのとまったく同じではありません。AFNetworking の背景ベースの実装には、独自の欠点と特異性が伴うと思います。AFURLSessionManagerNSURLSessionNSURLSession

私としては、持続的なバックグラウンドNSURLSessionアップロードで得た成功はすべて、ストック API のみを使用したものです。


質問等への対応

  • AFNetworking について: 一般的な Web API I/O に使用します。NSURLSession が登場したとき、AFNetworking はバックグラウンドでのアプリ操作を確実にサポートしていなかったので、私はそれを使用しませんでした。バックグラウンドの痛みとかすみを経験したためか、「今、 2 つの問題NSURLSessionがあります」というルーブリックの下で AFNetworking のバックグラウンドを確認します。しかし、おそらく彼らは今までにナッツを割ったのでしょう。

    • 私は1つを目指して努力していNSURLSessionます。私はセッションの作成と破棄について無頓着になり始めましたが、これがいくつかの本当に厄介な問題を引き起こしていることがわかりました。経験はこれで異なるようです。

    • 私はデフォルトを使用していますHTTPMaximumConnectionsPerHostが、問題はありません。Apple のドキュメントはデフォルト値について沈黙していますが、私が選択したランダムな特定のデバイス/OS で lldb が教えてくれることは次のとおり
      (lldb) p [config HTTPMaximumConnectionsPerHost] (NSInteger) $0 = 4
      です。

    • FWIW、バックグラウンドNSURLSessions はブロック インターフェイスをサポートしていません。デリゲートのみです。

于 2014-08-15T01:56:04.103 に答える