NSManagedObjectContexts和多线程

时间:2010-11-23 17:49:19

标签: iphone multithreading core-data nsmanagedobjectcontext

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

  1. 主线
  2. 主线程后台同步(同步 有服务器的地方)
  3. 天气预报 线程(地理编码中的地方) 背景)
  4. 在所有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]; 进行通话是否安全?因为这似乎解决了它。我只是不知道,如果我不小心打开潘多拉的盒子......

    此致

    塞巴斯蒂安

1 个答案:

答案 0 :(得分:1)

我认为您的应用程序结构会让您陷入危险境地。听起来像竞争条件是一些线程“A”在您从存储字典中删除MOC之前消失了。因此,您尝试在线程“A”上发送消息,然后它就会消失。

而是这样想:

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

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