Многопоточное использование основных данных (NSOperationQueue и NSManagedObjectContext)

В документации Apple Core Data для Concurrency с основными данными они перечисляют предпочтительный метод безопасности потоков, поскольку используют отдельный NSManagedObjectContext для потока, с общим NSPsistentStoreCoordinator.

Если у меня есть ряд NSOperations, запущенных один за другим в NSOperationQueue, будут ли большие накладные расходы, создающие контекст с каждой задачей?

Если NSOperationQueue имеет максимальное количество одновременных операций 1, многие из моих операций будут использовать один и тот же поток. Могу ли я использовать словарь потоков для создания одного NSManagedObjectContext для потока? Если я это сделаю, у меня будут проблемы с очисткой моих контекстов позже?

Каков правильный способ использования Core Data в этом случае?

Ответы

Ответ 1

Правильный способ использования Core Data в этом случае - создать отдельный NSManagedObjectContext для каждой операции или иметь единственный контекст, который вы заблокируете (через -[NSManagedObjectContext lock] перед использованием и -[NSManagedObjectContext unlock] после использования). Заблокированный подход может иметь смысл, если операции являются последовательными и нет других потоков, использующих контекст.

Какой подход к использованию является эмпирическим вопросом, который не может быть обеспечен без данных. Слишком много переменных имеют общее правило. Жесткие номера от тестирования производительности - единственный способ принять обоснованное решение.

Ответ 2

Операции, запущенные с использованием NSOperationQueue, с использованием максимального количества одновременных операций 1, не будут запускать все операции в одном потоке. Операции будут выполняться один за другим, но каждый раз будет создан новый поток.

Таким образом, создание объектов в словаре потоков будет малопривлекательным.

Ответ 3

Пока этот вопрос устарел, он фактически находится в верхней части результатов поиска Google в разделе "NSMangedObjectContext threading", поэтому я просто напишу новый ответ.

Новый "предпочтительный" метод - использовать initWithConcurrencyType: и сообщить MOC, является ли он основным потоком MOC или вторичным потоком moc. Затем вы можете использовать новые методы executeBlock: и executeBlockAndWait: на нем, и MOC позаботится о сериализации операций над его "родным" потоком.

Затем возникает вопрос, как вы разумно справляетесь с объединением данных между различными MOC, которые могут появиться вашим приложением, а также тысячами других деталей, которые делают жизнь "забавой" в качестве программиста.