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 时更新 NSManagedObject