NSManagedObjectContexts 和多线程

Posted

技术标签:

【中文标题】NSManagedObjectContexts 和多线程【英文标题】:NSManagedObjectContexts and Multithreading 【发布时间】:2010-11-23 17:49:19 【问题描述】:

假设我们有一个应用程序需要显示一个地点列表并在 3 个线程上运行:

    主线程 主线程后台同步(同步 有服务器的地方) 地理编码 线程(对 背景)

在所有 3 个线程中,我都有专门的 NSManagedObjectContexts(MOC)。如果每个 MOC 都可以更改基础数据(例如,主线程可以将地点添加到您的收藏夹,而后台同步可以更改地点的名称,而地理编码线程会添加纬度/经度信息),则应用程序必须注册 @987654322 @ 在每个线程中,然后将mergeChangesFromContextDidSaveNotification 传播到其他线程中相应的其他 MOC,如果一个 MOC 被保存(不仅仅是将它们合并到主线程的 MOC 中),对吗???

因为我现在正在这样做,但感觉不对:(

我有一本字典,我用它来保存当前正在运行的线程及其 MOC。每当其中一个 MOC 弹出 NSManagedObjectContextDidSaveNotification 时,我都会遍历该数组并将 mergeChangesFromContextDidSaveNotification 发送到所有其他 MOC/线程。当然,我还在NSThreadWillExitNotification 中添加了一个观察者,这样当其中一个线程用完时,我就可以从数组中移除 Thread/MOC。字典的所有添加/删除操作都被锁定。 这就是我现在有点卡住的地方。有时,当我打电话时

   [moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:) 
onThread:thread 
withObject:notification 
waitUntilDone:YES];

在遍历 MOC/线程字典时,我收到以下异常:

[NSManagedObjectContext performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform

显然,这是由竞争条件引起的。在遍历字典时(我只在提取其对象数组时锁定它),其中一个线程退出,因此引用不再有效。但是,如果我将字典锁放在整个循环的前面,我会遇到死锁,因为调用

[moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:) 
onThread:thread 
withObject:notification 
waitUntilDone:YES];

在某些情况下,循环内需要永远(还不知道为什么),从而导致整个应用程序停止。 在这种情况下使用waitUntilDone:NO 进行通话是否安全?因为这似乎可以解决它。我只是不知道,如果我不小心用这个打开了潘多拉的盒子......

问候,

塞巴斯蒂安

【问题讨论】:

【参考方案1】:

我认为您的应用程序结构将您置于危险境地。在我看来,竞争条件是在您从存储字典中删除 MOC 之前,一些线程“A”消失了。因此,您尝试在线程“A”上向它发送一条消息,它就会死掉。

不如这样想:

每个线程都有一个线程本地对象,您可以将其存储在线程本地存储中(请参阅 NSThread 文档,查找 threadDictionary) 该对象在您的线程开始工作时创建,并设置给定线程使用的 MOC 该对象还注册保存通知,并在线程工作的生命周期内监控它们 在线程工作结束时,该对象被销毁。

通过这种方式,您可以封装托管对象上下文的生命周期,并将其直接绑定到将引用它的通知机制。通过将监视器对象存储在线程本地存储中,您还可以将这两个关注点与线程的生命周期联系起来。

【讨论】:

以上是关于NSManagedObjectContexts 和多线程的主要内容,如果未能解决你的问题,请参考以下文章

兄弟 NSManagedObjectContexts 如何交互?

NSManagedObjectContexts 和多线程

合并 NSManagedObjectContexts 之间的更改(多线程)

使用不同的 NSManagedObjectContexts 时更新 NSManagedObject

NSConcurrencyType 用于在同一队列上使用独立的 NSManagedObjectContexts

在核心数据管理类中处理 NSManagedObjectContexts