“performBlockAndWait:”块未执行

时间:2015-10-05 13:13:36

标签: ios core-data concurrency nsmanagedobjectcontext

我有一个类似的方法:

- (void)handleUpdate
{
   dispatch_sync(dispatch_get_main_queue(), ^{
      NSArray *objectIDs = [self.objectsInMainContext valueForKeyPath:@"objectID"];

      [self.privateContext performBlockAndWait: ^{
         // Some processing
      }];
   });
}

我所谓的mainContext与主队列相关联,privateContext与私有队列相关联,并且是mainContext的子级。从privateContext的私有队列调用此方法,并且在达到nil调用时它不是performBlockAndWait:,但是执行不会进入块,并且此方法之后都没有任何代码到达了......

我可以在这里找到什么?

提前致谢

编辑:我在Xcode中没有出现错误,我在performBlockAndWait:块内的代码中设置的断点,并且在此方法调用之后根本没有达到。

编辑2:我更正了代码段,但我没有访问mainContext,而是访问与mainContext相关联的对象数组。

3 个答案:

答案 0 :(得分:0)

好吧,你的情况至少有一件事是错的:

在主线程上调用performBlockAndWait:(通过将其传递给主队列)。文档说performBlockAndWait:

  

在接收者的队列上同步执行给定的块。

作为该调用的结果,您将在主线程上获得死锁(当您在外部使用dispatch_sync时。

dispatch_async方式更新: 问题不会消失。那是因为你还在使用主队列(这意味着最后的主线程)和主CD上下文(也暗示主线程)。问题是你让主线程等到相同(主)线程上的作业完成 - 只是一个开箱即用的死锁。

答案 1 :(得分:0)

如果你说的话从私有队列调用handleUpdate,那么这是一个典型的死锁。

您在专用队列上调用dispatch_sync。这意味着"等到这个返回后再继续这个队列。"然后,在该块内,您将另一个块排队等待在私有队列上运行并且不会返回,直到它为止。队列正在等待自己,永远不会进展。

我怀疑你希望dispatch_sync在这里dispatch_async

答案 2 :(得分:0)

你有几个问题。

首先,您直接使用GCD序列化对NSMainQueueConcurrency MOC的访问。你应该从不使用除CoreData同步机制之外的任何东西来访问CoreData。是的,从主线程访问NSMainQueueConcurrencyType MOC是安全的。但是,您不应该直接使用GCD ...尤其是dispatch_sync

其次,您正在使用不可重入的dispatch_sync。它可能并且将会导致死锁。你几乎不应该使用这个功能。将它视为一种非常尖锐的工具,用于解决特定问题的唯一解决方案。

第三,您在子上下文中调用performBlockAndWait,这应该永远不会被执行,因为它可能导致死锁。通常,除非你真的知道自己在做什么,否则应该避免使用非异步线程模型。

您的代码应该更像这样。每个performBlock调用都会将一个块发布到一个消息队列中,该消息队列将独立于任何等待的线程进行处理。

- (void)handleUpdate
{
    [self.mainContext performBlock:^{
        NSArray *objectIDs = [self.objectsInMainContext valueForKeyPath:@"objectID"];
        [self.privateContext performBlock: ^{
            // Some processing with objectIDs
        }];
    });
}