假设我们有一个应用程序需要显示一个位置列表并在3个线程上运行:
在所有3个主题中,我都有NSManagedObjectContexts
个(MOC)。如果每个MOC可以更改基础数据(主线程可以将地点添加到您的收藏夹,而后台同步可以更改地点的名称,而地理编码线程添加lat / lng信息),应用程序将必须注册{{如果一个MOC被保存(不只是将它们合并到主线程的MOC中),那么在每个线程中然后将NSManagedObjectContextDidSaveNotification
传播到其他线程中相应的其他MOC,对吧???
因为现在我正在这样做,感觉不对:(
我有一个字典,我用它来保存当前正在运行的线程及其MOC。每当其中一个MOC弹出时,mergeChangesFromContextDidSaveNotification
I循环遍历此数组并将NSManagedObjectContextDidSaveNotification
发送给所有其他MOC /线程。当然,我还在mergeChangesFromContextDidSaveNotification
添加了一个观察者,这样当其中一个线程耗尽时我就可以从数组中删除Thread / MOC。字典的所有添加/删除操作都被锁定。
这就是我现在被困住的地方。有时候,当我打电话时
NSThreadWillExitNotification
当循环遍历MOC /线程字典时,我得到以下异常:
[moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:)
onThread:thread
withObject:notification
waitUntilDone:YES];
显然,这是由竞争条件引起的。在循环遍历字典时(我只在提取其对象数组时将其锁定),退出中的一个线程因此引用不再有效。但是,如果我把字典锁放在整个循环的前面,我会遇到死锁,因为调用
[NSManagedObjectContext performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform
循环中的在某些情况下永远需要(不知道为什么)并因此导致整个应用程序停止。
在这种情况下,使用[moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:)
onThread:thread
withObject:notification
waitUntilDone:YES];
进行通话是否安全?因为这似乎解决了它。我只是不知道,如果我不小心打开潘多拉的盒子......
此致
塞巴斯蒂安
答案 0 :(得分:1)
我认为您的应用程序结构会让您陷入危险境地。听起来像竞争条件是一些线程“A”在您从存储字典中删除MOC之前消失了。因此,您尝试在线程“A”上发送消息,然后它就会消失。
而是这样想:
通过这种方式,您可以封装托管对象上下文的生命周期,并将其直接绑定到将引用它的通知机制。通过将监视器对象存储在线程本地存储中,您还可以将这两个关注点与线程的生命周期联系起来。