2

Я читал большое количество блогов по основным процессам обработки данных ядра, но я не понимаю, как лучше всего управлять задачами BG Core Data, стреляя одновременно и уведомляя об этом к основному потоку MOC в неопределенное время.Несколько NSManagedObjectContexts - предотвращение условий гонки и взаимоблокировок

Я знаю, вы должны иметь 1 NSManagedObjectContext за NSThread и что подписавшись на NSManagedObjectContextDidSaveNotification наряду с использованием [context performBlock я получаю некоторые хорошее асинхронное выполнение задач.

То есть, я бегу много задач асинхронно, я не 100% знаю, когда некоторые будут перекрываться, и я наблюдал гонки условий в виде ...

  • BG MOC 1 оттеняет на его задачи
  • BG MOC 2 оттеняет на его задачи
  • BG MOC 2 завершает задачу и сохранить уведомление отправляется
  • BG MOC 1 завершает задачи, а затем вытирает BG MOC 2s изменения

Мой общий вопрос Как я могу решить условия гонки в нескольких MOC?

  1. Если правильное поведение должно иметь 1 MOC на поток .. Могу ли я создать Ивар NSThread и поставить все мои Core Data работают на него? Таким образом, у меня может быть один MOC, который работает синхронно с самим собой?

  2. Я читал, что NSLock может быть решением, позволяющим избежать доступа к определенному коду из нескольких потоков одновременно. Но я не знаю, что я должен блокировать? Метод «Сохранить контекст»? Постоянный магазин (кажется, делает многопоточность бессмысленным)?

  3. И наконец, могу ли я пометить/номер/имя моего MOC? если я знаю, что другие задачи запущены, я могу хранить уведомления и обрабатывать их в порядке их создания, чтобы гарантировать, что данные не будут перезаписаны? Рекомендуется

ответ

14
  1. один МОС на поток. Есть исключения, но это общее правило по-прежнему сохраняется. Не создавайте объекты NSThread. Только не надо. Слишком больно. Вместо этого используйте блоки или экземпляры NSOperation. Их легче заглушить и защитить от большой боли.

  2. Не используйте блокировки с данными сердечника. Core Data делает свою собственную блокировку при правильном использовании, и если вы бросаете блокировки вокруг вас, вы будете вызывать проблемы. В идеале вам должно быть никогда не нужно, чтобы вызвать замок в современной Objective-C.

  3. Вы не можете назвать MOC, кроме ссылок на ivar или ссылки на свойства. Вам тоже не нужно.

Чистейший способ сделать многопоточность с Core Data выглядит следующим образом:

  • У вас есть главный MOC нити/UI. Это ваш единственный источник истины. Ваш пользовательский интерфейс загружается из него и записывается на него.
  • Любой фоновый процесс выполняется в NSOperation или аналогичной конструкции. Вы создаете MOC внутри этой конструкции, и это - ребенок контекст к основному контексту.
  • Когда вы сохраняете дочерние элементы, изменения будут объединены с родителем (который является UI MOC).
  • Установите политику слияния, которая подходит для вашего основного MOC. Если вы считаете, что вам нужны разные политики для разных ситуаций, тогда вы должны переработать то, как вы делаете.

В идеале каждый фоновый процесс должен быть силосом данных, который может работать сам по себе, не сталкиваясь с другим процессом. Если у вас есть столкновение, это проблема слияния, которую вам необходимо решить в вашей бизнес-логике.

Если у вас есть ситуация, когда две фоновые операции будут ударять по одной и той же части данных, вы должны запускать их последовательно, а не параллельно. Параллельные изменения для тех же данных - это ожидание боли, не делайте этого.

Вы можете контролировать, являются ли вещи последовательными или параллельными, используя экземпляры NSOperationQueue.

Следуйте этим правилам, и у вас не будет условий гонки или тупиков.

+0

Отличный ответ, большое спасибо. Я не использовал 'NSOperation' /' NSOperationQueue' в моей реализации, поэтому я начну там. Рад получить твердую НЕТ во всех моих изворотливых идеях. – Magoo

+1

«NSOperation или аналогичная конструкция. Вы создаете MOC вместо этой конструкции», должен ли быть «внутри этой конструкции»? –

+0

Спасибо @IanDundas, исправлено. –