问题描述
我遇到的问题几乎与此人在此描述的问题完全相同,但未得到回答:
这里是问题:
我有一个父MOC设置与NSPrivateQueueConcurrencyType和持久存储协调器集,它有一个子MOC设置与NSMainQueueConcurrencyType 。这个想法是大多数长时间的努力工作和保存可以在私人MOC上完成,从而阻止主线程阻止UI。不幸的是,我似乎遇到了一些导致死锁的情况。
如果子MOC(在主线程上)使用NSFetchedResultsController执行获取,父上下文发送一个-executeFetchRequest:它可以创建一个死锁。两个操作都是在performBlock的上下文中完成的:对于它们各自的MOC,尽管文档似乎表明在没有performBlock:的主线程上使用主线程并发类型MOC是很好的。
看来,私有队列正在等待主线程上的子上下文已经锁定的PSC锁。看起来,子上下文(当持有PSC锁时)试图将dispatch_sync分配给父上下文,因此它们都在等待对方。
是PriveQueue - > MainQueue支持的配置?看起来大多数人在主线程上仍然有父上下文。
主线程如下所示:
私有队列堆栈看起来像这样:
#0 0x960f8876在__psynch_mutexwait $ b#1 0x97e9e6af in pthread_mutex_lock()
#2 0x0172ec22 in - [_ PFLock lock]()
#3 0x0172ebfa in - [NSPersistentStoreCoordinator lock]()
#4 0x01746a8c in - [NSManagedObjectContext (NSManagedObjectContext(Additions)executeFetchRequest:] at / Users / mlink / Code /目录下的[NSManagedObjectContext executeFetchRequest:error:]()
#6 0x0009d49f中的内容(_NSInternalAdditions)lockObjectStore]()
#5 0x01745030 - 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在/Users/mlink/Code/x/x/FBUser.m:461
#9 0x0180f9f3在developerSubmittedBlockToNSManagedObjectContextPerform_privateasync()
#10 0x04954ecf在_dispatch_queue_drain()
#11 0x04954d28在_dispatch_queue_invoke()
#12 0x049544af在_dispatch_worker_thread2()
#13 0x97ea1b24在_pthread_wqthread()
#14 0x97ea36fe在start_wqthread $ b
他也写道:
我开始认为问题是NSFetchedResultsController,它总是困在performFetch:当这些死锁发生时。大多数时候,它会被卡住,试图在一个对象中的错误,因为它要求它的部分名称。作为一个测试,我试图重现FRC做什么,并执行executeFetchRequest:然后迭代通过结果要求每个对象的部分名称。这不会导致死锁。如果我离开FRC做performFetch:在我做我的测试后,它仍然会死锁在那里。我99%肯定FRC有嵌套上下文的同步问题。
问题:有人知道为什么会出现这个问题吗?你知道如何解决它吗?这是一个错误?
我只是阅读其中fabrice truillot de chambrier建议不要使用嵌套上下文。他引用了文章。 p>
从该文章:
这似乎正是您的问题。
I have a problem that is almost identical to the problem described by this person here, but it hasn't get answered:
Here is the problem:
I have a parent MOC setup with NSPrivateQueueConcurrencyType and a persistent store coordinator set, it has a child MOC setup with NSMainQueueConcurrencyType. The idea being most of the long hard work and saves can be done on the private MOC freeing the main thread from blocking the UI. Unfortunately I seem to be running into a couple of situations that cause deadlocks.
If the child MOC (on the main thread) is performing a fetch with NSFetchedResultsController the parent context is sent an -executeFetchRequest: it can create a deadlock. Both operations are done within the context of a performBlock: for their respective MOCs although the docs seem to indicate that using a main thread concurrency type MOC on the main thread without performBlock: is fine.
It appears that the private queue is waiting on the PSCs lock which the child context on the main thread has already locked. It appears that the child context (while holding the PSCs lock) is trying to dispatch_sync to the parent context and thus they are both waiting for each other.
Is PriveQueue -> MainQueue a supported configuration? It seems most people still have the parent context on the main thread.
The main thread looks like this:
the private queue stack looks like this:
#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 ()
He also writes this:
I'm starting to think the problem is with NSFetchedResultsController which is always stuck at performFetch: when these deadlocks occur. Most of the time it will be stuck trying to fault in an object as a result of asking for it's section name. As a test I tried to reproduce what the FRC does and performed the executeFetchRequest: and then iterated through the results asking each object for it's section name. And this doesn't cause a deadlock. If I leave the FRC to do performFetch: after I do my test it will still deadlock there. I'm 99% sure that the FRC has a synchronization problem with nested contexts.
Question: Does anybody know why this problem occurs? Do you know how to solve it? Is this a bug?
I just read this SO posting where fabrice truillot de chambrier recommends not to use nested contexts at present. He gives a reference to the article Core Data Growing Pains.
From that article:
This seems to describe exactly your issue.
这篇关于核心数据嵌套受管对象上下文和频繁死锁/冻结的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!