我有一个几乎与这个人描述的问题完全相同的问题,但它还没有得到答案:
问题如下:
我已经设置了一个拥有NSPrivateQueueConcurrencyType和持久存储协调器的父MOC,并且设置了一个使用NSMainQueueConcurrencyType的子MOC。其想法是,大部分长时间而艰难的工作和保存可以在私有MOC上完成,从而释放主线程以防止阻塞UI。不幸的是,似乎遇到了一些会导致死锁的情况。
如果子MOC(在主线程上)正在使用NSFetchedResultsController执行取回操作,则将向父上下文发送-executeFetchRequest:可能会造成死锁。虽然文档似乎表明在主线程上使用具有主线程并发类型的MOC而不使用performBlock:也是可以的。
似乎私有队列正在等待PSC的锁,而主线程上的子上下文已经锁定了该锁。似乎子上下文(在持有PSC锁的同时)正在尝试dispatch_sync到父上下文,因此它们都在等待对方。
PriveQueue-> MainQueue是受支持的配置吗?似乎大多数人仍然将父上下文放在主线程上。
主线程看起来像这样:
> #0 0x960f6c5e in semaphore_wait_trap () > #1 0x04956bb5 in _dispatch_thread_semaphore_wait () > #2 0x04955c8f in _dispatch_barrier_sync_f_slow () > #3 0x04955dea in dispatch_barrier_sync_f () > #4 0x01797de5 in _perform () > #5 0x01798547 in -[NSManagedObjectContext(_NestedContextSupport) newValuesForObjectWithID:withContext:error:] () > #6 0x0176416b in _PFFaultHandlerLookupRow () > #7 0x01763f97 in -[NSFaultHandler fulfillFault:withContext:forIndex:] () > #8 0x01763b75 in _PF_FulfillDeferredFault () > #9 0x017639f2 in _sharedIMPL_pvfk_core () > #10 0x017681a0 in _pvfk_11 () > #11 0x0001b322 in -[FBUser sectionName] at /Users/mlink/Code/x/x/FBUser.m:62 > #12 0x011a8813 in _NSGetUsingKeyValueGetter () > #13 0x017a0652 in -[NSManagedObject valueForKey:] () > #14 0x011ab8d5 in -[NSObject(NSKeyValueCoding) valueForKeyPath:] () > #15 0x01851f72 in -[NSFetchedResultsController(PrivateMethods) _sectionNameForObject:] () > #16 0x01853af6 in -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:] () > #17 0x01850ea6 in -[NSFetchedResultsController performFetch:] () > #18 0x0003a4fc in __62-[SYFriendsTableViewController updateFetchedResultsController]_block_invoke_0 () > #19 0x01797af3 in developerSubmittedBlockToNSManagedObjectContextPerform () > #20 0x049554f0 in _dispatch_main_queue_callback_4CF () > #21 0x01b3e833 in __CFRunLoopRun () > #22 0x01b3ddb4 in CFRunLoopRunSpecific () > #23 0x01b3dccb in CFRunLoopRunInMode () > #24 0x023d6879 in GSEventRunModal () > #25 0x023d693e in GSEventRun () > #26 0x0089aa9b in UIApplicationMain () > #27 0x00002656 in main at /Users/mlink/Code/x/x/main.mm:16
私有队列堆栈长这样:
#0 0x960f8876 in __psynch_mutexwait () #1 0x97e9e6af in pthread_mutex_lock () #2 0x0172ec22 in -[_PFLock lock] () #3 0x0172ebfa in -[NSPersistentStoreCoordinator lock] () #4 0x01746a8c in -[NSManagedObjectContext(_NSInternalAdditions) lockObjectStore] () #5 0x01745030 in -[NSManagedObjectContext executeFetchRequest:error:] () #6 0x0009d49f in -[NSManagedObjectContext(Additions) executeFetchRequest:] at /Users/mlink/Code/objc/C/C/NSManagedObjectContext+Additions.m:44 #7 0x0002177f in +[FBUser usersForFbids:inManagedObjectContext:] at /Users/mlink/Code/x/x/FBUser.m:435 #8 0x00021fc0 in __77+[FBUser updateUserFromGraphValues:inManagedObjectContext:completionHandler:]_block_invoke_0 at /Users/mlink/Code/x/x/FBUser.m:461 #9 0x0180f9f3 in developerSubmittedBlockToNSManagedObjectContextPerform_privateasync () #10 0x04954ecf in _dispatch_queue_drain () #11 0x04954d28 in _dispatch_queue_invoke () #12 0x049544af in _dispatch_worker_thread2 () #13 0x97ea1b24 in _pthread_wqthread () #14 0x97ea36fe in start_wqthread ()
他还写了这句话:
我开始认为问题出在 NSFetchedResultsController 上,当死锁发生时它总是被卡在 performFetch: 上。大部分时间它都会卡在尝试获取一个对象的 section 名称时,试图将其加载入内存。作为测试,我尝试重现 FRC 所做的操作,执行了 executeFetchRequest: 方法并遍历结果,逐个询问每个对象的 section 名称,但这并没有导致死锁。如果我让 FRC 在我的测试之后继续执行 performFetch:,它仍然会卡在那里。我有 99% 的把握认为 FRC 存在与嵌套上下文同步的问题。
问题:有人知道这个问题为什么会发生吗?您知道如何解决它吗?这是一个 bug 吗?