保存托管对象上下文会在iOS 5的performBlock中创建死锁

时间:2012-07-13 10:53:43

标签: objective-c ios core-data deadlock nsmanagedobjectcontext

我一直在寻找这个问题的解决方案很长一段时间,并且已经达到了一个。

我正在开发一款包含核心数据的iOS应用。我创建了两个托管对象上下文(MOC),它指向同一个持久性存储协调器。一个MOC(称为self.moc)以主队列并发方式启动,而另一个mov(称为self.bmoc)以私有队列并发方式启动。我已确保self.moc仅在主线程上运行,self.bmoc仅在其performBlockperformBlockAndWait块内运行。

但是,我遇到了这种奇怪的情况,我的应用程序冻结在[self.bmoc save:nil]行。由于保存操作在performBlock块内执行,因此我没有看到它到达死锁的原因。由于它在该行冻结,即使我使用[self.bmoc save:&error]而不是nil,我也无法收到错误。

以下是重现问题的代码。虽然我有许多类似于下面的功能,但只有这个会产生问题。我无法确定问题的原因,非常感谢任何见解。谢谢!

-(void)createEmptyUserData {
    [self.bmoc performBlock:^{
        User* user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:self.bmoc];
        /* sets user object */
        [self.bmoc save:nil];
    }];
}

注意:这段代码在主线程中执行。

1 个答案:

答案 0 :(得分:0)

在这种情况下,你有两个基本的原因让你“挂起”。

  1. 您对performBlockAndWait或其他一些同步线程/队列调用进行了嵌套调用。

  2. 您的其中一个块未返回,并且永远无法运行。

  3. 通过查看“挂起”时每个正在运行的线程的堆栈,可以很容易地看到这两个。

    performBlock只需执行块并将其添加到队列中,然后立即返回。然后,其他一些线程将执行块从队列中弹出并执行它们。

    performBlockAndWait在调用线程的上下文中执行。基本上,它等待当前排队的执行块运行,然后它在当前线程上运行所请求的代码。

    直到通话结束后才会返回。

    所以,我敢打赌你有多个嵌套调用performBlockAndWait或者你的一个异步执行块没有完成。

    在挂起时查看堆栈......

    或者,记录块执行,这样您就可以看到每个块的启动和退出时间。