dispatch_sync到主线程上发生的后台队列(阻止在后台线程上设置后台管理对象上下文)

时间:2014-08-11 23:44:14

标签: core-data concurrency nsmanagedobjectcontext

我一直在尝试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等...)以保证块将在主线程以外的线程上执行之外,还有其它方法。

2 个答案:

答案 0 :(得分:0)

您似乎对您正在使用的调度功能感到困惑。在你的代码中它是" _sync",但在散文中它是" _async"。 dispatch_sync的目的是阻塞当前线程,直到某些内容完成,因此这将是您编写它的方式。请改为尝试dispatch_async。

答案 1 :(得分:0)

  

因为performblock *方法是在同一个队列上执行的   managedobjectcontext是在

上创建的

这句话是完全错误的。

使用performBlock的唯一方法是使用私有队列或主队列,每次调用performBlock都会将块排入适当的队列,无论涉及哪个线程/队列创建MOC。

现在,您的死锁是由performBlockAndWait使用,其行为与performBlock不同。 performBlockAndWait将导致调用线程等待,直到该块可以与MOCs调度队列同步执行。

此外,根本不保证某些代码块运行在哪个线程上......除了“主”队列的情况。

最后,应该很少,如果使用performBlockAndWait。是的,它是可重入的,但它也可能导致死锁。它应该仅在特定情况下使用,在这种情况下,您确定无法从任何其他块调用被调用的代码。如果您的代码是异步的,那应该是非常罕见的。它应该是。

相关问题