1

我的应用程序具有NSOperation获取和操作托管对象的子类。我的应用程序还定期从数据库中清除行,这可能导致以下竞争条件:

  • 后台操作获取一堆对象(从特定于线程的上下文中)。它将遍历这些对象并使用它们的属性做一些事情。
  • 在主托管对象上下文中删除了一堆行。
  • 后台操作访问从主上下文中删除的对象的属性。这导致一个'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault'

理想情况下,即使在 main context 中删除了一个对象,也可以对 NSOperation 获取的对象进行操作。我认为实现这一目标的最佳方法是:

  • 调用[request setReturnsObjectsAsFaults:NO]以确保 Core Data 不会尝试为不再存在于主上下文中的对象执行故障。这里的问题是我可能需要访问对象的关系,(据我了解)仍然会出错。
  • 预先遍历托管对象并将我需要的属性复制到单独的非托管对象中。这里的问题是(我认为)我需要同步/锁定这部分,以防在完成复制之前在主上下文中删除了一个对象。

我错过了一些明显的东西吗?看起来我想要完成的事情并没有太不寻常。谢谢你的帮助。

4

3 回答 3

0

你说每个线程都有自己的上下文。那挺好的。但是,它们还需要与彼此的更改保持同步(如何取决于它们的层次结构)。

是全部分配给同一个持久存储协调器,还是它们具有父/子关系?

兄弟姐妹应该监视来自其他兄弟姐妹的 NSManagedObjectContextObjectsDidChangeNotification。当子上下文保存时,父母会自动收到通知。

于 2012-05-22T21:32:39.040 回答
0

我最终通过在同一个队列上执行获取和删除来缓解这个问题。

于 2012-10-21T22:57:13.290 回答
0

好问题,我只能提供部分答案,我也很想知道这一点。不幸的是,您自己的解决方案更多的是一种解决方法,但并不是真正的答案。如果后台操作很长,又不能在主线程上运行怎么办?

我可以说的一件事是您不必调用[request setReturnsObjectsAsFaults:NO],因为提取请求会将数据加载到行缓存中,并且当某个提取的对象发生故障时不会返回数据库(请参阅 Apples 文档中的 NSFetchRequest )。不过,这对人际关系没有帮助。

我尝试了以下方法:

  1. NSManagedObjectContextWillSave收到通知时,等待当前后台任务完成并防止新任务以类似的方式开始

    -(void)contextWillSave:(NSNotification *)notification {
        dispatch_sync(self.backgroundQueue, ^{
            self.suspendBackgroundOperation = YES;
        });
    }
    
  2. NSManagedObjectContextDidSave在通知上取消设置suspendBackgroundOperation

然而,dispatch_sync 调用引入了可能的死锁,因此这也不起作用(请参阅我的相关问题)。另外,它仍然会阻塞主线程,直到可能冗长的后台操作完成。

于 2013-03-26T13:05:51.243 回答