performBlockAndWait creates deadlock

一世执手 提交于 2019-12-03 15:55:34
fabrice truillot de chambrier

Let's imagine you are calling myFunction from the main thread. Let's imagine [DatabaseDelegate sharedDelegate].parent.managedObjectContext is scheduled on the main thread.

With [backgroundContext performBlockAndWait:] you are scheduling a block on the context private background queue. Blocking the main thread.

With [.parent.managedObjectContext performBlockAndWait:], you are scheduling a block on the main thread, blocking the private queue.

But the main thread is blocked already. So the block will never execute. And performBlockAndWait: will never returns.

Deadlock.

Use asynchronously scheduled blocks, with completion blocks.

You don't have to wait. Your background work executes, then, before it is done, it kicks off work on the main thread, and before it is done, it does your "someOperation." You could replace it with async and it will still work.

Looking at this code, there is no reason to use the blocking versions...

+ (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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!