Ho letto il capitolo di Marcus Zarra sul multithreading nel suo libro di Core Data e ho esaminato abbastanza attentamente il suo codice di esempio. Ma il suo codice e altri che ho trovato altrove sembrano essere focalizzati in processi in background che fanno non devono essere consapevoli l'uno dell'altro. Questi esempi sono utili per importare una struttura ad albero, ma non riguardano l'importazione di una struttura più generale (complessa), come un grafo aciclico diretto.Core Data e multithreading
Nel mio caso, sto tentando di analizzare una gerarchia di classi C++ e vorrei utilizzare il maggior numero possibile di NSOperations. Vorrei creare un'istanza NSManagedObject per ogni classe incontrata e vorrei unire diversi NSManagedObjectContexts ogni volta che ne viene salvato uno.
Per inciso: sono in grado di far funzionare le cose con una sola NSOperation che itera su file e si analizza uno alla volta. In questa implementazione, il -mergeChanges: approccio che chiama -mergeChangesFromContextDidSaveNotification: sul MOC del thread principale funziona bene.
Ma idealmente, avrei una NSOperation iterare sui file sorgente e generare NSOperations per analizzare ogni file. Ho provato diversi approcci - ma non riesco a farlo bene. Il più promettente era che ogni NSOperation osservasse NSManagedObjectContextDidSaveNotification. Con -mergeChanges: simile a questo:
- (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];
}
In sostanza, l'analisi del NSOperation main() controllati Ivar 'needsToMerge' periodicamente. Se era vero, allora -mergeChangesFromContextDidSaveNotification: veniva chiamato sul MOC locale con NSNotifications memorizzate nella cache. E quindi needsToMerge è stato ripristinato. Se la notifica è stata originata localmente, al thread principale è stato detto di eseguire -mergeChangesFromContextDidSaveNotification: sul suo MOC.
sono sicuro che ci sia una buona ragione per cui questo non ha funzionato e perché ottengo questo:
avvertimento: Annullamento di chiamata - Codice objc sullo stack del thread corrente rende questo non sicuri.
ho anche cercato di usare il blocco di NSPeristentStoreCoordinator per controllare l'accesso - ma questo è problematico se si tiene durante una chiamata per -save di NSManagedObjectContext: metodo perché -save: notificherà osservatori interessati di salvare l'evento e -mergeChangesFromContextDidSaveNotification: sembra bloccare il tentativo di acquisire il blocco di PSC.
Sembra proprio che questo dovrebbe essere molto più semplice.
questa è una buona soluzione. Per quanto mi riguarda, probabilmente dovrei applicare changeNotifications prima di cercare un oggetto oltre a prima del salvataggio, ma sarebbe facile. A quanto ho capito, tutti i thread (eccetto il thread principale) sarebbero istanze di questa sottoclasse. È questo il caso? – westsider
@Westsider tutti gli NSOper che devono unire il contesto dovrebbero essere una sottoclasse di esso. Fondamentalmente suggerisco di creare una classe NSOperationManagedOobjectContextAware che abbia un metodo mergeChanges e le 3 proprietà changeNotifications, changeNotificationsLock, localManagedObjectContext –