performBlockAndWait创建僵局(performBlockAndWait create

2019-07-31 16:59发布

我写的是执行一些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两个块已执行后,才返回。

谢谢!

Answer 1:

让我们想象一下,你在呼唤myFunction主线程。 让我们想象一下[DatabaseDelegate sharedDelegate].parent.managedObjectContext被安排在主线程上。

[backgroundContext performBlockAndWait:]您正在调度上下文私人背景队列的块。 阻塞主线程。

[.parent.managedObjectContext performBlockAndWait:] ,你在主线程调度块,阻断专用队列。

但主线程已阻塞。 所以,该块将永远不会执行。 而performBlockAndWait:永远不会返回。

僵局。

使用异步调度块,以完成块。



Answer 2:

你不必等待。 你的工作背景来执行,那么, 它完成之前 ,它揭开序幕工作在主线程上,它完成之前,它的“someOperation。” 你可以用异步取代它,它仍然可以工作。

看着这个代码,没有理由使用阻塞版本...

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

    [backgroundContext performBlock:^{
      // Asynchronous... but every command in this block will run before this
      // block returns...
      MyObject *bla = create_my_object_in:backgroundContext;

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

      [[DatabaseDelegate sharedDelegate].parent.managedObjectContext performBlock:^{
        // Asynchronous, but this whole block will execute...
        [[DatabaseDelegate sharedDelegate].parent updateChangeCount:UIDocumentChangeDone];

        // Do some more stuff
        // This will not run until after the stuff above in this block runs...
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [queue addOperation:someOperation];
      }];
      // You will reach here BEFORE the code in the previous block executes, but
      // the "someOperation" is in that block, so it will not run until that
      // block is done.
    }];
    // Likewise, you will reach here before the above work is done, but everything
    // will still happen in the right order relative to each other.
   return;
}


文章来源: performBlockAndWait creates deadlock