2011-10-10 8 views
15

Sto iniziando a pensare che la risposta alla mia domanda sia "No", ma sono ancora confuso e incerto su questo. Quindi per favore conferma. Ho già imparato la necessità di fare attenzione quando si utilizzano i dati di base con più thread. Gli oggetti NSManagedObjectContext non devono superare i limiti del thread. Essendo un principiante con entrambi i thread e Core Data, ho felicemente scoperto che GCD dovrebbe rendere questo più facile.Una coda di invio GCD è sufficiente per limitare un contesto Core Data a un singolo thread

Ingenuamente forse, ho quindi pensato di creare semplicemente una coda di distribuzione GCD dedicata per gestire i dati di base (o anche, se necessario, disporre di più code di invio ciascuna con il proprio contesto di dati di base). Sarebbe stato semplice.

Ma ora mi rendo conto che un grande vantaggio delle code di invio GCD è che gestisce e utilizza più thread in base alle esigenze. Quindi, se ho capito bene, i compiti che ho consegnato alla stessa coda di invio, potrebbero finire per essere eseguiti in thread diversi, potenziando potenzialmente un contesto di dati di base da un thread a un altro, e fare in modo che le cose vadano storte. È giusto?

Ho letto molte domande e risposte correlate, ad esempio Core Data and threads/Grand Central Dispatch, ma rimango un po 'confuso. La risposta accettata a questa domanda, utilizzando le code GCD, garantisce che venga creato un nuovo contesto su ciascun thread, ma non sottolinea la necessità di farlo. Un'altra risposta dice "Potresti eseguire tutto il lavoro di CoreData su una coda denominata com.yourcompany.appname.dataaccess" sembra implicare che finché il lavoro di Core Data è limitato a una coda di invio GCD, allora tutto è OK. Forse non lo è.

risposta

19

Aggiornamento: Come @adib indica in un commento, l'approccio all'accesso al contesto oggetto gestito serializzato è stato modificato in iOS 9 e MacOS X 10.11. NSConfinementConcurrencyType, la strategia di confinamento del thread, è ora ritirata a favore di NSPrivateQueueConcurrencyType e NSMainQueueConcurrencyType. In altre parole, interrompi l'utilizzo dei thread per l'accesso simultaneo agli oggetti Core Data e inizia invece a utilizzare GCD. È necessario utilizzare la coda di invio principale o quella associata al MOC, a seconda di come si configura il MOC e non di una coda della propria creazione. Questo è facile da fare usando i metodi -performBlock: o -performBlockAndWait: di NSManagedObject.


Risposta breve: Utilizzando una coda di invio di serie in grado di fornire l'accesso serializzato a un contesto oggetto gestito, e questo è un modo accettabile per attuare la strategia "filo confinamento", anche se GCD può effettivamente utilizzare più thread. risposta

più lunga:

La risposta accettata a questa domanda, utilizzando le code GCD, fa assicurarsi che un nuovo contesto viene creato su ogni thread, ma non indica la necessità di fare questo .

La grande cosa che dovete ricordare è che è necessario evitare di modificare il contesto oggetto gestito da due diversi thread allo stesso tempo. Ciò potrebbe mettere il contesto in uno stato incoerente, e nulla di buono può venire da questo. Pertanto, il tipo di della coda di invio che si utilizza è importante: una coda di invio simultanea consentirebbe a più attività di procedere simultaneamente e, se entrambi utilizzano lo stesso contesto, si avranno problemi. Se si utilizza una coda di invio seriale, d'altra parte, potrebbero essere eseguite due o più attività su thread diversi, ma le attività verranno eseguite in ordine e verrà eseguita solo un'attività alla volta.Questo è molto simile all'esecuzione di tutte le attività sullo stesso thread, almeno per quanto riguarda il mantenimento della coerenza del contesto.

Vedere this question e answer per una spiegazione molto più dettagliata.

Ecco come Core Data ha sempre funzionato. La sezione Concurrency with Core Data della Guida alla programmazione dei dati fondamentali fornisce consigli su come procedere se si decide di utilizzare un singolo contesto in più thread. Parla principalmente della necessità di stare molto attenti a bloccare il contesto ogni volta che lo si accede. Il punto di tutto ciò che blocca, però, è quello di garantire che due o più thread non provino a utilizzare il contesto simultaneamente. L'utilizzo di una coda di invio serializzata raggiunge lo stesso obiettivo: poiché viene eseguita una sola attività nella coda alla volta, non è possibile che due o più attività proveranno a utilizzare il contesto contemporaneamente.

+1

Ottima risposta, ma nel thread collegato, la confusione di bbum sembra implicare che l'oggetto MOC non può attraversare i limiti del thread, anche se l'accesso è serializzato. Ben lo afferma in modo specifico, quindi cosa dovremmo fare? –

+2

@SedateAlien, all'inizio della sua risposta, Ben indica la nota nella [documentazione] (http://tinyurl.com/6dlg75j) che dice: *** Nota: ** È possibile utilizzare thread, code di operazioni seriali o code di invio per concorrenza. Per motivi di concisione, questo articolo usa "thread" in tutto per riferirsi a uno di questi. "* Quindi, nel resto della sua risposta, o nella documentazione, è possibile sostituire * la coda di invio seriale * per * thread *. , la cosa essenziale è evitare di usare contemporaneamente lo stesso contesto per cose diverse.Tutti i tre meccanismi menzionati possono essere utilizzati per ottenere ciò.Impostazione – Caleb

+0

Quindi devo creare il MOC su detta coda seriale? Se creo l'oggetto MOC fuori coda, ma usarlo solo in coda, è accettabile o richiede problemi? –

0

AFAIK sei corretto; GCD non fornisce garanzie sul thread in cui viene eseguita la coda. I blocchi e le chiamate di funzione inviati alla coda verranno eseguiti uno alla volta, ma se i dati di base fanno qualcosa con il thread corrente, ad es. installa una sorgente di loop di esecuzione o un osservatore, le cose probabilmente non funzioneranno come previsto.

Tuttavia, su Mac OS X 10.7, NSManagedObjectContext può essere impostato per l'esecuzione sul thread principale, su un thread separato o in una coda privata.

Problemi correlati