我写的是执行一些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
两个块已执行后,才返回。
谢谢!
让我们想象一下,你在呼唤myFunction
主线程。 让我们想象一下[DatabaseDelegate sharedDelegate].parent.managedObjectContext
被安排在主线程上。
与[backgroundContext performBlockAndWait:]
您正在调度上下文私人背景队列的块。 阻塞主线程。
与[.parent.managedObjectContext performBlockAndWait:]
,你在主线程调度块,阻断专用队列。
但主线程已阻塞。 所以,该块将永远不会执行。 而performBlockAndWait:
永远不会返回。
僵局。
使用异步调度块,以完成块。
你不必等待。 你的工作背景来执行,那么, 它完成之前 ,它揭开序幕工作在主线程上,它完成之前,它的“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;
}