performBlockAndWait创建死锁 [英] performBlockAndWait creates deadlock

查看:408
本文介绍了performBlockAndWait创建死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

//做一些更多的东西
NSOperationQueue * queue = [[NSOperationQueue alloc] init];
[queue addOperation:someOperation];
}];
}];
return;
}



我希望返回只发生在 addOperation:someOperation]
这似乎工作大多数情况下,但我有一个case,当这个函数从未返回。它似乎是死锁,我怀疑是因为 performBlockAndWait



我的问题是: p>

(1)有人可以解释为什么会发生这种死锁吗?





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



谢谢!让我们假设你正在从主线程调用 myFunction 。 让我们假设 [DatabaseDelegate sharedDelegate] .parent.managedObjectContext 预定在主线程上。



使用 [backgroundContext performBlockAndWait:] 您正在调度上下文专用后台队列上的块。阻止主线程。



使用 [。parent.managedObjectContext performBlockAndWait:] 主线程,阻塞私有队列。



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



死锁。



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


I am writing a function that performs some CoreData stuff. I want the function to return only after all the CoreData operations have executed. The CoreData stuff involves creating an object in a background context, then doing some more stuff in the parent context:

+ (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;
}

I want the return to only happen after [queue addOperation:someOperation]. This seems to work most of the cases, but I have had one case when this function never returned. It seemed like it was deadlocked, and I suspect it is because of performBlockAndWait.

My questions are:

(1) Can someone explain why this deadlock occurs?

and

(2) What is the right way of achieving the same functionality? The requirement is that myFunction returns only after both blocks have been executed.

Thank you!

解决方案

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.

这篇关于performBlockAndWait创建死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆