2

我长期以来一直在寻找解决这个问题的方法,但还没有找到。

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

但是,我遇到了这种奇怪的情况,我的应用程序冻结[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];
    }];
}

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

4

1 回答 1

0

在这种情况下,您有两个基本原因会“挂起”。

  1. 您有一个对 performBlockAndWait 或其他同步线程/队列调用的嵌套调用。

  2. 你的一个块没有返回,并且永远运行。

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

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

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

在调用完成之前它不会返回。

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

查看挂起时的堆栈...

或者,记录您的块执行,以便您可以查看每个块的启动和退出时间。

于 2012-07-13T18:11:29.267 回答