objective-c - performBlockAndWait 创建死锁

标签 objective-c ios core-data deadlock nsmanagedobjectcontext

我正在编写一个函数来执行一些 CoreData 的东西。我希望函数仅在 所有 CoreData 操作执行完毕后返回。 CoreData 涉及在后台上下文中创建一个对象,然后在父上下文中执行更多操作:

+ (void) myFunction
    NSManagedObjectContext *backgroundContext = [DatabaseDelegate sharedDelegate].backgroundContext;

    [backgroundContext performBlockAndWait:^{
      MyObject *bla = create_my_object_in:backgroundContext;

      [backgroundContext obtainPermanentIDsForObjects:[[backgroundContext insertedObjects] allObjects] error:nil];
      [backgroundContext save:nil];

      [[DatabaseDelegate sharedDelegate].parent.managedObjectContext performBlockAndWait:^{
        [[DatabaseDelegate sharedDelegate].parent updateChangeCount:UIDocumentChangeDone];

        // Do some more stuff
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperation:someOperation];
      }];
    }];
   return;
}

我希望返回仅发生在 [queue addOperation:someOperation] 之后。 这似乎适用于大多数情况,但我曾遇到过此函数从未返回的情况。它似乎陷入了僵局,我怀疑这是因为performBlockAndWait

我的问题是:

(1) 谁能解释一下为什么会出现这种死锁?

(2) 实现相同功能的正确方法是什么?要求是 myFunction 仅在两个 block 都已执行后返回。

谢谢!

最佳答案

假设您正在从主线程调用 myFunction。让我们想象一下 [DatabaseDelegate sharedDelegate].parent.managedObjectContext 被安排在主线程上。

使用 [backgroundContext performBlockAndWait:],您可以在上下文专用后台队列上安排一个 block 。阻塞主线程。

使用 [.parent.managedObjectContext performBlockAndWait:],您在主线程上调度一个 block ,阻塞私有(private)队列。

但是主线程已经被阻塞了。所以这个 block 永远不会执行。 performBlockAndWait: 永远不会返回。

死锁。

使用带有完成 block 的异步调度 block 。

关于objective-c - performBlockAndWait 创建死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12500627/

相关文章:

ios - 如何在 sqlite iOS 中查找现有文件夹名称

iOS UIWebView 完全看不懂不止一个@font-face?

iphone - 在核心数据中搜索具有空 "to-many"关系的所有对象

ios - UIButton 无法在 iPhone 屏幕底部正确注册触摸

java - 推送通知警报文本的最大长度是多少?

Objective-c/iOS - 使用 Safari 打开本地 html 文件

ios 核心数据 - 将实体记录复制到另一个实体

ios - 识别核心数据属性类型

ios - 在哪里释放在同一类的不同方法中使用的 NSArray

objective-c - 具有输入数组的方法