Pergunta

Eu tenho um aplicativo que puxa os dados da web, analisa-los, e compila os resultados em uma interface de pesquisa. Uma vez que os dados não são co-dependente, fazia sentido para multi-thread do aplicativo para executar múltiplas buscas e analisa simultaneamente. Eu uso NSInvocationOperation em uma busca e objeto de análise que eu escrevi para executar esta função.

No objeto controlador Eu tenho o seguinte método:

-(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];
 }
}

O aplicativo depende Core Data, que eu recolhi é principalmente enfiar inseguro. Eu tenho um NSManagedObjectContext diferente para cada operação de busca / parse (e um para o controlador), e só passar o NSManagedObjectId entre as operações ou objetos de proxy.

As operações de comunicar os resultados de análise concluída ao seu controlador através de um objeto NSConnection. O controlador constrói o NSConnection usando um objeto NSMachPort, define-se como o objeto raiz, e dá o mesmo objeto NSConnection a cada um dos alvos dos NSInvocationOperations. O controlador então enfileira o NSInvocationOperation para execução em seu próprio NSOperationQueue.

Na busca threader objeto Eu tenho o seguinte método:

-(void) executeSearchAndParse
{ 
 id parentServer = [threadConnection rootProxy];
 [parentServer setProtocolForProxy:@protocol(SearchParseProtocol)];

 NSArray *importResults = [targetSchema generatedDataSetIds];

 [parentServer schemaFinished:targetSchema];
 [parentServer addSearchResults:importResults];
}

Creio ter seguido o exemplo da Apple de comunicação inter-thread genérico dado aqui .

Eu tenho que dizer que na maioria das vezes, isso funciona muito bem: As notificações do NSConnection rootProxy são lançados no loop de execução na thread principal como esperado e espera para retirada até que o objeto controlador está pronto. No entanto, em alguns dos meus casos de teste que provoca Core Data para moer a uma parada brusca, porque às vezes as mensagens torná-lo para o objeto controlador no mesmo segmento como o objeto NSInvocationOperation que está chamando o objeto rootProxy .

Eu coloquei um ponto depurador no controlador na mensagem que é enviada quando a operação de busca / análise estiver concluída, e com certeza, às vezes (só às vezes) o thread em execução é não o principal. Alguém tem uma idéia de por que isso pode ocorrer? Ou, se existe uma maneira mais simples de construir inter-thread comunicação assíncrona? OR é a minha abordagem para Core Data totalmente fora de forma?

Agradecemos antecipadamente!

Foi útil?

Solução

Não vejo mal qualquer coisa com sua abordagem e usaram NSConnection de maneira semelhante antes. A única coisa que eu vejo é que eu usei apenas NSPort em vez de usar NSMachPort explicitamente.

Ou, se existe uma maneira mais simples de construir inter-thread comunicação assíncrona?

Eu não acho que a Apple está promovendo objetos ditributed para a comunicação inter-thread mais. IIRC esta suposição se baseia principalmente em documentação que tenho visto mencionado o que realmente promove DOs para a comunicação inter-thread, mas que desde então têm sido removido ou editado.

Eu também acho que as relacionadas com a rosca performSelector: métodos em NSObject são muito mais fáceis de usar:

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

(enquanto o segundo só está disponível a partir de 10,5 por diante).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top