Имам приложение, което извлича данни от мрежата, анализира ги и компилира резултатите в интерфейс за търсене. Тъй като данните не са взаимно зависими, има смисъл приложението да бъде многонишково, за да изпълнява едновременно множество извличания и анализи. Използвам 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. Контролерът конструира NSConnection с помощта на обект NSMachPort, задава се като основен обект и дава същия обект NSConnection на всяка от целите на NSInvocationOperations. След това контролерът поставя NSInvocationOperation в опашка за изпълнение в своя собствена NSOperationQueue.
В обекта за нишки за търсене имам следния метод:
-(void) executeSearchAndParse
{
id parentServer = [threadConnection rootProxy];
[parentServer setProtocolForProxy:@protocol(SearchParseProtocol)];
NSArray *importResults = [targetSchema generatedDataSetIds];
[parentServer schemaFinished:targetSchema];
[parentServer addSearchResults:importResults];
}
Вярвам, че последвах примера на Apple за обща комуникация между нишки, дадена тук.
Трябва да кажа, че през повечето време това работи прекрасно: уведомленията от rootProxy на NSConnection се публикуват в цикъла за изпълнение в главната нишка, както се очаква, и изчакват за приемане, докато обектът на контролера е готов. Въпреки това, в някои от моите тестови случаи това кара основните данни да спират до скърцане, защото понякога съобщенията стигат до обекта на контролера в същата нишка като обекта NSInvocationOperation, който извиква rootProxy обекта.
Поставих точка за отстраняване на грешки в контролера на съобщението, което се изпраща, когато операцията за търсене/анализ е завършена, и разбира се, понякога (само понякога) изпълняваната нишка не е основната. Някой има ли идея защо може да се случи това? Или има по-прост начин за конструиране на асинхронна комуникация между нишки? ИЛИ подходът ми за Core Data е напълно неподходящ?
Благодаря предварително!