2

Instagram風のように、一度にたくさんの場所に画像をアップロードするアプリがあります。

これは、非同期の周りに多数NSOperationQueueのラッパーを実行するでセットアップされます。NSOperationNSURLConnection

このように始まるほとんどの質問は、「呼び出し元のスレッドが戻る前に結合されているため、コールバックが呼び出されません。これはそのような質問ではありません。期待どおりにコールバックを取得しています、アプリを何らかの形で妨げています。ホームボタンを押したときのバックグラウンドから。サンドボックスのせいでこれを完全にブロックすることはできないといつも思っていましたが、どういうわけかそれを実行しました。操作の実行中にホームボタンを押しても、操作が完了するまで何も起こりません。どの時点(20〜30秒後)でアプリが適切に背景になります。

** NBこれは、シングルコアプロセッサデバイスでのみ発生するようです。iPhone 4でのみ再現できますが、4SまたはiPad3では再現できません。*

まだ興味がある?これが私の設定です:

self.uploadQueue = [[NSOperationQueue alloc] init];
[self.uploadQueue setMaxConcurrentOperationCount:1];
[self.uploadQueue setSuspended:YES];

後で、キューに操作を追加し、一時停止を解除して開始します。NSOperationこれらのサブクラスのコードは次のとおりです。

- (BOOL)isConcurrent { return YES; }
- (BOOL)isExecuting { return self.executing; }
- (BOOL)isFinished { return self.finished; }

- (void)start {
    // Omitted: check for cancel...
    // Omitted: check if setup to run

    [self willChangeValueForKey:@"isExecuting"];
    self.executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

    [self.sharer share];    
    CFRunLoopRun();
}


- (void)completeOperation {
    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];
    self.executing = NO;
    self.finished = YES;
    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
    CFRunLoopStop(CFRunLoopGetCurrent());
}

このshareメソッドは非同期をセットアップし、次のNSURLConnectionように起動します。

- (void)share {
    // Omitted: connection setup
    [NSURLConnection sendAsynchronousRequest:postRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *error){
        // handle error or success, then call
        [self.currentOperation completeOperation];
    }];

私が解決しようとしている副作用は別として、コード想定どおりに機能し、コールバックが呼び出され、スレッドは必要な限り存続し、操作キューは指定されたものだけを実行します一度に操作の数。

私は何を試しましたか?私は試した:

  1. でNSURLConnectionを呼び出し[NSOperationQueue currentQueue]ます。これにより、非同期接続がブロックをコールバックしませんでした。
  2. 各NSOperationをstartメソッドのメインスレッドに強制します。これでは問題は解決せず、コードが機能しなくなったり、UIがフリーズしたりすることもありました。
  3. 適切なディスパッチスレッドを取得するために、可変配列とGCDを使用して独自のキューを実装します。動作させることができませんでした。
  4. 操作での同期NSURLConnections。それは私にとってオプションではないので、私は実際にこれを試しませんでした。Facebook iOS SDKなどの一部のネットワークフレームワークには、同期オプションがありません。

ホームボタンを押した後、操作が完了する前に実行を一時停止しても、何も興味深いことはありません。ロックまたは実行が終了するのを待っているメインスレッドには何もないようです。

スレッド1スレッド2

私はこれを完全なボゾのように設定していますか?ここで何が起こっているのですか、どうすれば修正できますか?

4

1 に答える 1

0

編集:

このネットワーク関連のものはすべて赤いニシンだったことがわかりました。どういうわけか踏み台に戻るのを妨げていたのは、いくつかのループしているCAAnimationsでした。

元の推測:

CFRunLoopRun私の推測では、startメソッドを呼び出すべきではありません。並行操作のstartメソッドは、操作が完了する前に戻り、後で終了することが期待されます。システムが他のタスクをディスパッチするために必要なGCDロック(スレッド?)を保持している可能性があります。

を介してスレッドを独占する必要がある場合はCFRunLoopRun、独自のスレッドを開始しstartてから戻る必要があります。ただし、NSOperationを使用せずに、メインスレッドから(すでに非同期の)URL接続を開始し、それぞれが終了したときに共有するものの配列を保持する方が簡単だと思います。

実際、問題はCFRunLoopStop(CFRunLoopGetCurrent())次のとおりだと思います。これをメインスレッドで実行しているので、メイン実行ループを停止しています。

于 2012-06-29T01:26:33.873 に答える