私は、ASI HTTPを使用してWebサーバーから定期的にデータをフェッチし、そのデータを処理してUIにユーザーに関連するものを表示するアプリケーションを作成しています。データは、単一のサーバー上のさまざまなリクエストから取得されます。データ自体は特定の順序で処理する必要があります。データのブロックの1つは、他のブロックよりもはるかに大きくなっています。
データの処理中にUIをロックしないようにするために、を使用しNSOperationQueue
て別のスレッドでデータ処理を実行しようとしました。これは、約90%の確率で正常に機能します。ただし、残りの10%の時間では、データの最大ブロックがメインスレッドで処理されているため、UIが1〜2秒間ブロックされます。アプリケーションには、異なるタブに2つのMKMapViewが含まれています。両方のMKMapViewsタブがロードされると、メインスレッドでデータの最大ブロックが処理されている時間の割合が50%を超えて増加します(これは、より多くの同時アクティビティがある場合にこれが発生するという仮定を示しているようです)。
NSOperationQueue
メインスレッドでコードを実行しないようにする方法はありますか?
私はそれを増やしたり減らしたりして遊んでみましたNSOperationQueue
–setMaxConcurrentOperationCount:
が、この問題に実際の変化はありませんでした。
これは、定期的な更新を開始するコードです。
- (void)refreshAll{
// Create Operations
ServerRefreshOperation * smallDataProcessor1Op = [[ServerRefreshOperation alloc] initWithDelegate:_smallDataProcessor1];
ServerRefreshOperation * smallDataProcessor2Op = [[ServerRefreshOperation alloc] initWithDelegate:_smallDataProcessor2];
ServerRefreshOperation * smallDataProcessor3Op = [[ServerRefreshOperation alloc] initWithDelegate:_smallDataProcessor3];
ServerRefreshOperation * smallDataProcessor4Op = [[ServerRefreshOperation alloc] initWithDelegate:_smallDataProcessor4];
ServerRefreshOperation * smallDataProcessor5Op = [[ServerRefreshOperation alloc] initWithDelegate:_smallDataProcessor5];
ServerRefreshOperation * hugeDataProcessorOp = [[ServerRefreshOperation alloc] initWithDelegate:_hugeDataProcessor];
// Create dependency graph (for response processing)
[HugeDataProcessorOp addDependency:smallDataProcessor4Op.operation];
[smallDataProcessor5Op addDependency:smallDataProcessor4Op.operation];
[smallDataProcessor4Op addDependency:smallDataProcessor3Op.operation];
[smallDataProcessor4Op addDependency:smallDataProcessor2Op.operation];
[smallDataProcessor4Op addDependency:smallDataProcessor1Op.operation];
// Start be sending all requests to server (startAsynchronous directly calls the ASIHTTPRequest startAsynchronous method)
[smallDataProcessor1Op startAsynchronous];
[smallDataProcessor2Op startAsynchronous];
[smallDataProcessor3Op startAsynchronous];
[smallDataProcessor4Op startAsynchronous];
[smallDataProcessor5Op startAsynchronous];
[hugeDataProcessorOp startAsynchronous];
}
これは、データ処理を開始するASIHTTP完了ブロックを設定するコードです。
[_request setCompletionBlock:^{
[self.delegate setResponseString:_request.responseString];
[[MyModel queue] addOperation:operation]; // operation is a NSInvocationOperation that calls the delegate parse method
}];
エントリポイントのすべてのNSInvocationOperationInvokedメソッドにこのコードブロックを追加しました。
if([NSThread isMainThread]){
NSLog(@"****************************Running <operation x> on Main thread");
}
UIがフリーズするたびに行が印刷されます。これは、操作全体がメインスレッドで実行されていることを示しています。実際にはhugeDataProcessorOp
、メインスレッドで実行されるのは常にです。これは、サーバーから常に最後に回答を受け取る操作だからだと思います。