Webからデータを取得して解析し、検索インターフェイスで結果をコンパイルするアプリケーションがあります。データは相互依存していないため、アプリケーションをマルチスレッド化して、複数のフェッチと解析を同時に実行することは理にかなっています。この関数を実行するために作成した検索および解析オブジェクトでNSInvocationOperationを使用します。
コントローラオブジェクトには、次のメソッドがあります。
-(void) searchAndParseAsynchronously {
NSPort *serverPort = [NSMachPort port];
NSConnection *serverConnection = [NSConnection connectionWithReceivePort:serverPort sendPort:serverPort];
[serverConnection setRootObject:self];
for (NSURL *urlToProcess in self.urlsToFetch)
{
BaseSearchParser *searcherForURL = [BaseSearchParser newSearchParserWithParameters:self.searchParams];
searcherForURL.urlToDocument = urlToDocument;
SearchThreader *searchThreader = [SearchThreader new];
searchThreader.threadConnection = comConnection;
searchThreader.targetSchema = searcherForURL;
NSInvocationOperation *threaderOperation = [[NSInvocationOperation alloc] initWithTarget:searchThreader
selector:@selector(executeSearchParse)
object:nil];
[self.operationQueue addOperation:threaderOperation];
}
}
アプリケーションはコアデータに依存していますが、私が収集したものはほとんどスレッドセーフではありません。検索/解析操作ごとに(およびコントローラー用に)異なるNSManagedObjectContextがあり、操作間またはプロキシオブジェクト間でのみNSManagedObjectIdを渡します。
操作は、完了した解析結果をNSConnectionオブジェクトを介してコントローラーに戻します。コントローラは、NSMachPortオブジェクトを使用してNSConnectionを構築し、それ自体をルートオブジェクトとして設定し、NSInvocationOperationsの各ターゲットに同じNSConnectionオブジェクトを提供します。次に、コントローラーは、NSInvocationOperationをエンキューして、独自のNSOperationQueueで実行します。
検索スレッダーオブジェクトには、次のメソッドがあります。
-(void) executeSearchAndParse
{
id parentServer = [threadConnection rootProxy];
[parentServer setProtocolForProxy:@protocol(SearchParseProtocol)];
NSArray *importResults = [targetSchema generatedDataSetIds];
[parentServer schemaFinished:targetSchema];
[parentServer addSearchResults:importResults];
}
ここに示した一般的なスレッド間通信のAppleの例に従ったと思います。
ほとんどの場合、これは美しく機能します。NSConnectionrootProxyからの通知は、期待どおりにメインスレッドの実行ループに送信され、コントローラーオブジェクトの準備ができるまでピックアップを待ちます。ただし、一部のテストケースでは、rootProxyオブジェクトを呼び出しているNSInvocationOperationオブジェクトと同じスレッドのコントローラーオブジェクトにメッセージが届くことがあるため、CoreDataが急停止します。
検索/解析操作が完了したときに送信されるメッセージのコントローラーにデバッガーポイントを配置しました。確かに、実行中のスレッドがメインスレッドではない場合もあります。なぜこれが起こるのかについて誰かが考えていますか?または、スレッド間非同期通信を構築するためのより簡単な方法はありますか?または、Core Dataに対する私のアプローチは完全にオフキルターですか?
前もって感謝します!