Я прочитал главу Маркуса Зарры о многопоточности в своей книге «Основные данные» и довольно внимательно посмотрел на его образец кода. Но его код и другие, которые я нашел в другом месте, похоже, сосредоточены в фоновых процессах, которые не должны знать друг о друге. Эти примеры хороши для импорта древовидной структуры, но они не затрагивают импорт более общей (сложной) структуры, такой как направленный ациклический граф.Основные данные и многопоточность
В моем случае я пытаюсь проанализировать иерархию классов C++ и хотел бы использовать как можно больше NSOperations. Я хотел бы создать экземпляр NSManagedObject для каждого встреченного класса, и я хотел бы объединить различные NSManagedObjectContext, когда он будет сохранен.
В стороне: я могу заставить все работать с одним NSOperation, которое выполняет итерацию файлов и анализирует их по одному. В этой реализации метод -mergeChanges: подход, который вызывает -mergeChangesFromContextDidSaveNotification: в MOC основного потока работает хорошо.
Но, в идеале, я бы хотел, чтобы один NSPperation перебирал исходные файлы и запускал NSOperations для анализа каждого файла. Я попробовал несколько подходов - но, похоже, не все правильно. Наиболее перспективным было то, чтобы каждый NSOperation наблюдал NSManagedObjectContextDidSaveNotification. С -mergeChanges: глядя, как это:
- (void) mergeChanges:(NSNotification *)notification
{
// If locally originated, then trigger main thread to merge.
if ([notification object] == [self managedObjectContext])
{
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [appDelegate managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
return;
}
// If not locally originated, then flag need to merge with in this NSOperation's thread.
[self setNeedsToMerge:YES];
[self setMergeNotification:notification];
}
По существу, разбор NSOperation Мейн() проверяется Ивар 'needsToMerge' периодически. Если это правда, то -mergeChangesFromContextDidSaveNotification: вызывается в локальном MOC с кешированными NSNotifications. И затем requireToMerge был сброшен. Если уведомление возникло локально, то основной поток сказал, чтобы выполнить -mergeChangesFromContextDidSaveNotification: на своем MOC.
Я уверен, что есть хорошая причина, почему это не работает, и почему я получаю это:
предупреждение: Отмена вызова - ObjC код на стек текущего потока делает это небезопасно.
Я также попытался использовать блокировку NSPeristentStoreCoordinator для контроля доступа - но это проблематично, если оно проводится во время вызова -сохраняйте NSManagedObjectContext в: метод, потому что -save: уведомит заинтересованных наблюдателей сохранить событие и -mergeChangesFromContextDidSaveNotification: похоже, блокирует попытку приобретения блокировки PSC.
Просто кажется, что это должно быть намного проще.
это приятное решение. Для меня, вероятно, мне нужно будет применить changeNotifications до поиска объекта в дополнение к до сохранения - но это было бы легко. Насколько я понимаю, все потоки (кроме основного потока) будут экземплярами этого подкласса. Это так? – westsider
@ Всем всем NSOperation, которые должны объединить контекст, должен быть подкласс этого. В основном я предлагаю создать класс NSOperationManagedOobjectContextAware, который имеет метод mergeChanges и 3 свойства changeNotifications, changeNotificationsLock, localManagedObjectContext –