Core Data父ManagedObjectContext是否需要与子上下文共享并发类型?

时间:2011-12-07 23:27:03

标签: ios core-data

我可以将ManagedObjectContext的父上下文设置为具有不同并发类型的ManagedObjectContext吗?例如:

backgroundManagedObjectContext_ = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[backgroundManagedObjectContext_ setPersistentStoreCoordinator:coordinator];
managedObjectContext_ = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[managedObjectContext_ setParentContext:backgroundManagedObjectContext_];

我的目标是(希望)获得managedObjectContext_的快速保存(因为它只需要将内容保存到父内存上下文中),然后让backgroundManagedObjectContext_在其自己的队列中执行保存。除非我碰巧需要在后台保存之前从“前台”队列执行另一次保存,否则我的用户永远不会看到很长的保存时间。

我遇到了类似死锁的问题,但我不确定它们是否与此相关,或者我的问题是否在其他地方。


我可以或多或少地可靠地产生死锁的地方的详细信息:

我有一个主线程的托管对象上下文,它由一个具有私有队列并发类型的托管对象上下文支持,并且它有一个持久存储。

我有一些实体类型(大约5个),每个实体类型与另一个实体有一个或两个双向关系。

我的应用程序想要使用iCloud(我已为这些测试拨打了代码),因此它无法附带预先填充的数据库,它需要在检测到空数据库时构建它。

所以,当我看到一个空的数据库(在主线程上检查)时,我添加了除了一个实体类型之外的所有类型中的4个或8个,并且最后一个获得大约100个(所有添加都发生在主要数据库中)线)。主线程执行saveContext。在完成之后(没有错误),它要求其他托管对象上下文运行也执行saveContext的块。这个saveContext绝对是一个死锁参与者。这也是使用“背景”NSManagedObjectContext完成的唯一内容。

在此之后,确切的控制流程有点模糊,因为NSFetchedResultsController(所有给定的实体类型(具有~3个成员)具有简单的排序,批量大小为20左右)驱动下一轮核心数据活动,但有来自TableViewController的调用询问它需要管理多少项,即“获取结果控制器有多少结果”。那个电话是僵局的另一面。 (这一切都在主线程中)

1 个答案:

答案 0 :(得分:36)

根据我的经验,只要两个上下文都实现NSMainQueueConcurrencyTypeNSPrivateQueueConcurrencyType,就没有必要这样做。需要记住的重要一点是,当跨多个线程与托管对象上下文进行交互时,发送到上下文的所有消息都必须通过-performBlock:performBlockAndWait:发送。

在最近的一个项目中,我有一个父NSManagedObjectContext支持使用NSFetchedResultsController创建的NSMainQueueConcurrencyType。在那里,我使用NSManagedObjectContext创建了NSPrivateQueueConcurrencyType,并将NSMainQueueConcurrencyType设置为父级。现在,我的子上下文在添加新对象时可能包含可废弃的编辑,该对象最终会在由父上下文支持的NSFetchedResultsController支持的表视图中结束。当我准备保存我的编辑并将它们冒泡到父上下文时,代码看起来像这样。

// Save the child context first
[childContext performBlock:^{
    NSError *error = nil;
    [childContext save:&error];

    // Save the changes on the main context
    [parentContext performBlock:^{
        NSError *parentError = nil;
        [parentContext save:&parentError];
    }];
}];

现在我不能肯定地说这是正确的方法,因为目前这方面的文档非常稀少。如果您可以显示一些您认为导致死锁的代码,则可能会有所帮助。如果您在开发人员计划中,则可能需要查看今年有关核心数据的WWDC会话视频。我相信有两个,一个用于Mac OS X,一个用于iOS,基本上触及相同的想法,但每个都包含独特的信息。