PerformBlockAndWait против dispatch_sync (dispatch_get_main_queue ()

Utility.managedObjectContext().performBlockAndWait({

})

dispatch_sync(dispatch_get_main_queue(), {

})
  1. Любопытно, в чем разница между двумя приведенными выше кодами? контекст был создан с опцией .MainQueueConcurrencyType.
  2. Если я выполняю блоки в основной очереди, выполняются ли очереди в порядке FIFO? Или они могут перекрываться, операции смешиваются? т.е. (a1,a2,a3),(b1,b2,b3) может привести к (a1,b1,a2,a3,b2,b3)?

person János    schedule 14.10.2013    source источник


Ответы (1)


Здесь вы смешиваете две совершенно разные концепции, но, поскольку это основной поток/контекст/очередь, ваш микс замаскирован и «работает».

Методы performBlockAndWait: и performBlock: контекста управляемого объекта не дают никаких гарантий, в каком потоке выполняется блок, только безопасный доступ к данным, к которым осуществляется доступ/мутация. Поскольку ваш контекст относится к типу параллелизма основной очереди, это исключение в том, что безопасно касаться его объектов вне методов performBlockAndWait: и performBlock:, только в основном потоке. Поэтому, когда вы ставите свой блок в очередь для запуска в основной очереди, он гарантированно запускается в основном потоке, и, таким образом, ваши данные в безопасности.

Выполнение блока в основном потоке не является атомарным. Иначе какой смысл в многопоточности? Чтобы обеспечить безопасность данных, вы должны вызывать методы performBlockAndWait: и performBlock: при доступе к данным. Вам гарантируется, что запланированные блоки основной очереди будут выполняться без прерывания другими запланированными блоками основной очереди, а очереди контекста управляемого объекта (фоновые или основные) являются последовательными, поэтому только одному блоку будет разрешен одновременный доступ к данным.

person Leo Natan    schedule 12.05.2015
comment
обычно сохранение контекста идет вместе с другими вещами, такими как: (1) очистка контейнеров indexPath (2) сохранение контекста (3) будет вызван обратный вызов NSFetchedResultedController (4) контейнеры indexPath будут заполнены (5) вставка/удаление строк в tableView (6) снова чистка контейнеров indexPath - потому что мне нужен весь этот код в критической секции, вы говорите: не просто отправлять его в основную очередь с dispatch_sync, а использовать performBlockAndWait, я правильно понимаю? - person János; 12.05.2015
comment
Желательно, да. Не забудьте не обновлять пользовательский интерфейс из этого блока. Если у вас есть полученный контроллер результатов, и он привязан к контексту управляемого объекта основной очереди, он будет гарантированно вызываться в основном потоке, поэтому обновлять пользовательский интерфейс там будет безопасно. - person Leo Natan; 12.05.2015