1

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に対する私のアプローチは完全にオフキルターですか?

前もって感謝します!

4

1 に答える 1

1

私はあなたのアプローチに何も悪いことは見ていませんし、NSConnection以前も同じように使用しました。私が見る唯一のことは、明示的に使用NSPortする代わりに使用したことです。NSMachPort

または、スレッド間非同期通信を構築するためのより簡単な方法はありますか?

Appleはもはやスレッド間通信のために分散オブジェクトを宣伝しているとは思わない。IIRCのこの推測は、ほとんどの場合、スレッド間通信のDOを実際に促進するが、その後削除または編集された、私が言及したドキュメントに基づいています。

また、NSObjectのスレッド関連のperformSelector:メソッドの方がはるかに使いやすいと思います。

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait

(2番目のものは10.5以降でのみ使用可能です)。

于 2009-12-11T13:33:41.673 に答える