Przeczytałem rozdział Marcusa Zarry na temat wielowątkowości w jego książce danych podstawowych i przyjrzałem się dokładnie jego przykładowemu kodowi. Ale jego kod i inne, które znalazłem gdzie indziej wydają się być skoncentrowane w procesach działających w tle, które nie muszą być świadome siebie nawzajem. Te przykłady są dobre do importowania struktury drzewa - ale nie odnoszą się do importu bardziej ogólnej (złożonej) struktury, jak na przykład skierowany wykres acykliczny.Dane podstawowe i wielowątkowość
W moim przypadku próbuję parsować hierarchię klasy C++ i chciałbym użyć jak najwięcej NSOperations, jak to możliwe. Chciałbym utworzyć wystąpienie NSManagedObject dla każdej napotkanej klasy i chciałbym scalić różne NSManagedObjectContexts, gdy jeden jest zapisany.
Na marginesie: Jestem w stanie sprawić, że wszystko działa z pojedynczą NSOperacją, która iteruje pliki i parsuje je pojedynczo. W tej implementacji -mergeChanges: podejście, które wywołuje -mergeChangesFromContextDidSaveNotification: na MOC wątku głównego działa dobrze.
Ale najlepiej byłoby, gdyby jedna operacja powtórzyła iteracje plików źródłowych i odrodziła się w NSOperations, aby przeanalizować każdy plik. Próbowałem kilku podejść - ale nie mogę tego naprawić. Najbardziej obiecujące było to, aby każda NSOperation obserwowała NSManagedObjectContextDidSaveNotification. Z -mergeChanges: wygląda tak:
- (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];
}
Zasadniczo parsowania NSOperation na main() sprawdzone Ivar 'needsToMerge' okresowo. Jeśli było to prawdą, to wywoływano -mergeChangesFromContextDidSaveNotification: na lokalnym MOC z buforowanymi NSNotifications. A następnie needsToMerge został zresetowany. Jeśli powiadomienie pochodzi lokalnie, to główny wątek został poinformowany, aby wykonać -mergeChangesFromContextDidSaveNotification: na swoim MOC.
Jestem pewien, że istnieje dobry powód, dlaczego to nie działa i dlaczego mam to:
ostrzeżenie: Zakończenie połączenia - kod objc na stosie bieżący wątek sprawia to niebezpieczne.
Próbowałem również użyć blokady NSPeristentStoreCoordinator do kontroli dostępu - ale to jest problematyczne, jeśli odbywa się w trakcie rozmowy na -save NSManagedObjectContext za: Metoda bo -save: powiadomi zainteresowanych obserwatorów zapisać zdarzenie i -mergeChangesFromContextDidSaveNotification: wydaje się blokować próbę zdobycia blokady PSC.
Po prostu wydaje się, że powinno być o wiele łatwiej.
To jest dobre rozwiązanie. Dla mnie prawdopodobnie musiałbym zastosować changeNotifications przed wyszukiwaniem obiektu oprócz wcześniejszego zapisu - ale to byłoby łatwe. Jak rozumiem, wszystkie wątki (z wyjątkiem wątku głównego) byłyby instancjami tej podklasy. Czy tak jest? – westsider
@Wyzywanie wszystkiego, co musi scalić kontekst, powinno być jego podklasą. Zasadniczo proponuję utworzyć klasy NSOperationManagedOobjectContextAware, który ma metodę mergeChanges i 3 właściwości changeNotifications, changeNotificationsLock, localManagedObjectContext –