挂在mergeChangesFromContextDidSaveNotification(和合并冲突)

时间:2012-09-13 15:48:32

标签: objective-c ios core-data nsmanagedobjectcontext

总结:在多线程场景中调用[myMOC mergeChangesFromContextDidSaveNotification:notification]时,我的应用程序已挂起。

详细情况如下:

我的应用从服务器下载了大量数据,并在首次启动时将其存储在Core Data中。它有几个部分。解析整个过程需要几秒钟,大部分时间都花在了两个块上。所以为了加快速度,我将这两个块并行化了。这就是它的样子:

NSArray *arr = [self parseJsonData:downloadedNSData]; //turns NSData into JSON array
                     //using NSJSONSerialization
NSMutableArray __block *first = [[NSMutableArray alloc]init];
NSMutableArray __block *second = [[NSMutableArray alloc]init];

//put half of arr in first and half in second with a loop

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dipatch_group_create(); 
dispatch_group_async(group, queue, ^
   {
      for (id element in first)
      {
         [MyDataClass parseData:element]; //create NSManagedObject subclass, save
      }
      [self saveContext];
   });

    dispatch_group_async(group, queue, ^
   {
      for (id element in second)
      {
         [MyDataClass parseData:element]; //create NSManagedObject subclass, save
      }
      [self saveContext];
   });

  dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

[self saveContext]在MOC上调用save。这当然是在多个线程上完成的,所以我需要为每个线程创建一个单独的ManagedObjectContext。这是通过在此对象(self)上通过属性公开MOC来实现的,该对象维护NSMutableDictionary个线程名称(在description上调用NSThread)到{{1} }秒。访问时,如果没有NSManagedObjectContext的MOC,它会创建一个新的MOC,将其添加到字典中并存储它。创建每个MOC时,我订阅其更改通知:

[NSThread currentThread]

NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:createdMOC]; 中,我遍历我的上下文字典并在所有这些字典上调用mergeChanges,除了正在发生的线程的那个。更具体地说,我使用mergeChangesFromContextDidSaveNotification让每个MOC在为其创建的线程上执行此操作。

我还使用[performSelector:onThread:withObject:waitUntilDone:]NSLock方法围绕[myMOC save]锁定。如果我没有锁定那些,我得到“Cocoa error 133020”,apparently表示合并更改时出错。

所以,这就是我的日志记录告诉我的事情:

  • 线程1获取锁定以保存并开始保存
  • 合并上下文通知出现在线程1上。线程1获取用于合并更改的锁并开始该过程。它合并主线程MOC的更改,然后在为后台线程执行其中一个MOC时挂起。
  • 线程2开始保存,但永远不会获取保存锁,因为另一个线程试图合并更改时卡住了。

那么,为什么在合并变化时它会挂起?有没有更好的方法来处理这种情况?

更新:我尝试在mergeChanges电话周围使用[persistentStoreCoordinator lock]而不是仅使用[MOC save]锁定,但无济于事。我还尝试在其中一个NSLock来电中调用[NSThread sleepForTimeInterval:2]之前添加[self saveContext],但没有帮助。

更新2:也许这里更好的问题是我遇到合并冲突的原因(可可错误133020)。这是预期的吗?我是否正确进行合并(合并到除一个保存之外的所有上下文)?

更新3:我发布了another question来解决我正在进行多线程处理的更大背景。

2 个答案:

答案 0 :(得分:0)

当您创建NSManagedObject子类时,您将其插入到上下文中,因此您只能在属于上下文的队列/线程上执行此操作。

在上下文中调用-save同样如此。

在您的代码中,我认为您正在插入两个对象 - 每个对象都在自己的线程上。那不行。

答案 1 :(得分:-1)

我发布了this question更好地记录我的情况。我认为目前这个问题的范围有点狭窄。