performBlockAndWait创建死锁 [英] performBlockAndWait creates deadlock
问题描述
我编写一个函数来执行一些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屋!