2010-11-23 106 views
2

比方说,我们有需要显示的地点列表,并可以运行在3个线程的应用程序:NSManagedObjectContexts和多线程

  1. 主线
  2. 主线程后台同步(同步 地方与服务器)
  3. 天气预报 线程(地理编码在 背景的地方)

在所有3个线程我有d编号为NSManagedObjectContexts(MOCs)。如果每个MOC都可以更改底层数据(主线程可以将该地点添加到收藏夹中,而后台同步可以更改该地点的名称,而地址解码线程添加纬度/经度信息),则应用程序必须注册NSManagedObjectContextDidSaveNotification每个线程,然后散布mergeChangesFromContextDidSaveNotification到其他线程中的相应的其他线程,如果一个MOC得到保存(不只是合并到主线程的MOC),正确的???

因为现在我这样做,并没有觉得不对劲:(

我有一本字典,我使用到当前正在运行的线程保存它们的MOCS。每当MOCS的一个弹出NSManagedObjectContextDidSaveNotification我循环遍历这个数组并发送mergeChangesFromContextDidSaveNotification到所有其他的MOC/Threads。当然,我还在NSThreadWillExitNotification上添加了一个观察者,这样当其中一个线程用完时,我可以从数组中移除Thread/MOC。字典被锁定 这就是我现在有点被卡住的情况,有时当我打电话时

[moc performSelector:@selector(mergeChangesFromContextDidSaveNotification:) 
onThread:thread 
withObject:notification 
waitUntilDone:YES]; 
通过MOCS /线程词典循环时

,我得到下面的异常扔给我:

[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

我觉得你的应用程序结构,把你在危险的情况。在我看来,竞争条件是某些线程“A”会在您从存储字典中删除MOC之前消失。因此,您尝试在线程“A”上发送一条消息并将其终止。

反而觉得它是这样的:

  • 每个线程都有一个线程局部对象,您可以在线程本地存储中存储(见NSThread文档,寻找threadDictionary)
  • 创建该对象当你的线程开始这样做的时候,并设置一个给定的线程使用的MOC
  • 该对象还注册保存通知,并监视它们的线程工作的生命周期
  • 在线程的末尾工作这个对象是破坏者d。

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