我一直在尝试Marcus Zarra核心数据手册推荐的核心数据设置。该设置需要两个托管对象上下文。具有并发类型private的父moc。和孩子的主要背景。这背后的原因是主核心数据上下文可以具有超快速读/写,因为主上下文(在主队列上)的更改会传播到父级,而不是传播到磁盘。
然而,Zarra的核心数据初始化方法在同一个线程上设置每个上下文。由于performblock *方法是在创建managedobjectcontext的同一队列上执行的,因此听起来所有核心数据读/写都将在主队列上发生。通过在后台线程上设置私有上下文,这个堆栈不会更好吗?
这个想法让我编写了代码(受到Zarra书中代码的启发),类似于以下内容:
__block NSManagedObjectContext *private = nil;
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSPersistentStoreCoordinator *psc = nil;
psc = [self persistentStoreCoordinator];
NSUInteger type = NSPrivateQueueConcurrencyType;
private = [[NSManagedObjectContext alloc] initWithConcurrencyType:type];
[private setPersistentStoreCoordinator:psc];
});
NSManagedObjectContext *moc = nil;
type = NSMainQueueConcurrencyType;
moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:type];
[moc setParentContext:private];
_mainManagedObjectContext = moc;
_backgroundObjectContext = private;
...
当我像这样设置我的核心数据堆栈时,我最终会遇到来自performBlockAndWait的死锁,因为主线程等待自己释放以执行该工作块... ad infinitum。奇怪的是,我试图执行工作的队列不仅仅是任何全局队列 - 它是主线程。出于某种原因,dispatch_sync与其中一个内置全局队列(或我自己创建的dispatch_queue)不保证用于所选工作块的线程将是主线程以外的线程。除了低于gcd(例如使用nsthread等...)以保证块将在主线程以外的线程上执行之外,还有其它方法。
答案 0 :(得分:0)
您似乎对您正在使用的调度功能感到困惑。在你的代码中它是" _sync",但在散文中它是" _async"。 dispatch_sync的目的是阻塞当前线程,直到某些内容完成,因此这将是您编写它的方式。请改为尝试dispatch_async。
答案 1 :(得分:0)
因为performblock *方法是在同一个队列上执行的 managedobjectcontext是在
上创建的
这句话是完全错误的。
使用performBlock
的唯一方法是使用私有队列或主队列,每次调用performBlock
都会将块排入适当的队列,无论涉及哪个线程/队列创建MOC。
现在,您的死锁是由performBlockAndWait
使用,其行为与performBlock
不同。 performBlockAndWait
将导致调用线程等待,直到该块可以与MOCs调度队列同步执行。
此外,根本不保证某些代码块运行在哪个线程上......除了“主”队列的情况。
最后,应该很少,如果使用performBlockAndWait
。是的,它是可重入的,但它也可能导致死锁。它应该仅在特定情况下使用,在这种情况下,您确定无法从任何其他块调用被调用的代码。如果您的代码是异步的,那应该是非常罕见的。它应该是。