0

我有两个块通过 GCD 在用户定义的并发队列上同时调度。在块流中的某个时刻,它们必须访问同一组核心数据托管对象。不是显式地通过获取,而是通过已经获取的具有一对多关系集的对象。

据我了解,每个块都应该有自己的上下文,然后在完成时将两个上下文合并到主线程中的一个。

但是,我想知道创建 2 个上下文然后合并到第三个上下文的可行替代方法是执行以下操作:

- (void)someMethodThatAppliesToAdisjointSetWithRange:(NSRange)range fromSharedObject:(NSManagedObject*)someSharedObject
{
  //  Do some stuff...

  //  Create sortDescriptors

  __block NSArray* entities = nil;
  dispatch_sync(dispatch_get_main_queue(), ^{
    entities = [[[someSharedObject valueForKey:@"sprites"] sortedArrayUsingDescriptors:sortDescriptors] retain];
    entities = [entities subarrayWithRange:range]
  });

  for(id anEntity in entities)
  {
    //  STRICTLY retrieve properties from the entities
    //  And do stuff with these, BUT DON'T modify the entities themselves.
  }

  //  Continue doing stuff that has nothing to do with the managed objects.
}

- (void)dispatchMethod
{

  dispatch_async(_concurrentQueue, ^{
    [self someMethodThatAppliesToAdisjointSetWithRange:NSMakeRange(0, floor(pageData.count/2.)) fromSharedObject:someSharedObject];
  });

  dispatch_async(_concurrentQueue, ^{
    [self someMethodThatAppliesToAdisjointSetWithRange:NSMakeRange(floor(pageData.count/2.), ceil(pageData.count/2.)) fromSharedObject:someSharedObject];
  });
}

我对上面的想法是,主线程上的调度在并发流中创建了一个同步点,并且由于我什至没有修改自己的托管对象,所以应该没问题。然而,在一整天的测试中,我得到了一个核心数据“statement is still active”不一致的异常。所以现在我认为他上面的代码仍然不安全。尽管异常实际上可能是由应用程序中的其他代码引起的。

有什么想法吗?

4

1 回答 1

0

经验的答案是否定的,你不能。大概是因为对 managedObject 中关系的任何类型的访问都可能会出错,并且无论如何都需要上下文隐式地获取关系中的对象。

那是,

for(id anEntity in entities)
  {
    //  STRICTLY retrieve properties from the entities
    //  And do stuff with these, BUT DON'T modify the entities themselves.
  }

仍然需要访问 managedObjectContext。

使用两个本地上下文而不是建议的方法的相同代码不会导致“语句仍处于活动状态”异常。

于 2012-10-15T06:31:06.437 回答