我正在通过新创建的NSManagedObjectContext在后台线程(使用GCD)上执行一个代价高昂的获取(约5秒,约30,000个对象)由后台线程拥有。主线程在后台线程执行时等待[NSManagedObjectContext(_NSInternalAdditions)lockObjectStore]
但是,我没有得到在后台执行此操作的好处,因为主线程正在等待持久存储上的锁定并因此UI被冻结。这里的堆栈跟踪:
* thread #1: tid = 0x1c03, 0x3641be78 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) lockObjectStore], stop reason = breakpoint 1.1
frame #0: 0x3641be78 CoreData`-[NSManagedObjectContext(_NSInternalAdditions) lockObjectStore]
frame #1: 0x36432f06 CoreData`-[_PFManagedObjectReferenceQueue _processReferenceQueue:] + 1754
frame #2: 0x36435fd6 CoreData`_performRunLoopAction + 202
frame #3: 0x35ab9b1a CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 18
frame #4: 0x35ab7d56 CoreFoundation`__CFRunLoopDoObservers + 258
frame #5: 0x35ab80b0 CoreFoundation`__CFRunLoopRun + 760
frame #6: 0x35a3b4a4 CoreFoundation`CFRunLoopRunSpecific + 300
frame #7: 0x35a3b36c CoreFoundation`CFRunLoopRunInMode + 104
frame #8: 0x376d7438 GraphicsServices`GSEventRunModal + 136
frame #9: 0x33547cd4 UIKit`UIApplicationMain + 1080
frame #10: 0x000f337a MyApp`main + 90 at main.m:16
我(相信)我已经证实了我不是访问主线程的NSManagedObjectContext而这个后台线程正在做的工作。从堆栈跟踪中,很明显,我没有直接对Core Data做任何事情。但是有一些事件触发了对_processReferenceQueue的调用:这导致试图锁定商店。有没有人碰巧知道这个方法做了什么,以及如何防止它在我的后台线程执行其工作时被调用?
编辑
我开球此背景下取后,我没有做任何核心数据读取或在主线程上写道。这就是为什么这是如此令人费解。如果主线也在尝试做更多的工作,我预计会有争议,但这不是 - 至少,我没有要求它。没有读,不写,没有FRC。这就是为什么我想知道是否有人熟悉这个_processReferenceQueue方法。为什么会被叫?我能做些什么,导致它运行?
编辑
作为测试,我试图让MT的MOC进入状态,它没有未决的改变之前,我设置了蓝牙功能关闭做的获取,在希望它不会需要在_processReferenceQueue
中做任何需要商店锁定的工作。
在开始BT之前,我注意到在[MOC updatedObjects]
集合中有一个对象。插入或删除的组中没有对象。
在调用[MOC save]
之后,[MOC updatedObjects]
集合就像预期的那样是空的。
但是,一旦我开始BT,MT仍然试图锁定店内_processReferenceQueue
,尽管没有什么在MOC中应该是脏的。
我试过的下一件事(严格来说就是测试)是在开始BT之前调用[MOC reset]
。如预期的那样,[MOC updatedObjects]
集合在重置之后也是空的。在代码中的这一点上,我没有触及MT上的任何托管对象,直到BT完成其工作(所以我没有遇到任何问题,因为重置使我已经引用的托管对象无效)。然而,这一次,MT确实不是试图锁定_processReferenceQueue
中的持久存储。
这种行为暗示了我在启动BT后没有对MT上的MOC进行任何明确的操作。否则,MT会在_processReferenceQueue
内部或外部的某个点(读取或写入)请求锁定。但事实并非如此。
我不确定为什么最近保存的MOC需要后续锁定_processReferenceQueue
而最近重置的MOC不需要。
我会继续挖掘。
谢谢! 布赖恩
我有一个想法,但今天通过回答一个缺乏信息的问题已经烧了两次。请在后台线程中发布更多关于你在做什么的信息,以及你在主线程中做什么(例如,你是否在后台执行任何写操作,主线程中是否有FRC)。 ..等 –
另外,请记住,您不能跨线程传递提取的对象。在后台使用这些30k对象,或传递其ID。 –
以上更新。此外,即使我仅仅在背景上执行提取并忽略结果(作为测试),MT上的锁定也会发生。我确实将objectID传回MT。 – BrianJStafford