我有一个类似的方法:
- (void)handleUpdate
{
dispatch_sync(dispatch_get_main_queue(), ^{
NSArray *objectIDs = [self.objectsInMainContext valueForKeyPath:@"objectID"];
[self.privateContext performBlockAndWait: ^{
// Some processing
}];
});
}
我所谓的mainContext
与主队列相关联,privateContext
与私有队列相关联,并且是mainContext
的子级。从privateContext
的私有队列调用此方法,并且在达到nil
调用时它不是performBlockAndWait:
,但是执行不会进入块,并且此方法之后都没有任何代码到达了......
我可以在这里找到什么?
提前致谢
编辑:我在Xcode中没有出现错误,我在performBlockAndWait:
块内的代码中设置的断点,并且在此方法调用之后根本没有达到。
编辑2:我更正了代码段,但我没有访问mainContext
,而是访问与mainContext
相关联的对象数组。
答案 0 :(得分:0)
好吧,你的情况至少有一件事是错的:
在主线程上调用performBlockAndWait:
(通过将其传递给主队列)。文档说performBlockAndWait:
在接收者的队列上同步执行给定的块。
作为该调用的结果,您将在主线程上获得死锁(当您在外部使用dispatch_sync
时。
以dispatch_async
方式更新:
问题不会消失。那是因为你还在使用主队列(这意味着最后的主线程)和主CD上下文(也暗示主线程)。问题是你让主线程等到相同(主)线程上的作业完成 - 只是一个开箱即用的死锁。
答案 1 :(得分:0)
如果你说的话从私有队列调用handleUpdate
,那么这是一个典型的死锁。
您在专用队列上调用dispatch_sync
。这意味着"等到这个返回后再继续这个队列。"然后,在该块内,您将另一个块排队等待在私有队列上运行并且不会返回,直到它为止。队列正在等待自己,永远不会进展。
我怀疑你希望dispatch_sync
在这里dispatch_async
。
答案 2 :(得分:0)
你有几个问题。
首先,您直接使用GCD序列化对NSMainQueueConcurrency
MOC的访问。你应该从不使用除CoreData同步机制之外的任何东西来访问CoreData。是的,从主线程访问NSMainQueueConcurrencyType
MOC是安全的。但是,您不应该直接使用GCD ...尤其是dispatch_sync
。
其次,您正在使用不可重入的dispatch_sync
。它可能并且将会导致死锁。你几乎不应该使用这个功能。将它视为一种非常尖锐的工具,用于解决特定问题的唯一解决方案。
第三,您在子上下文中调用performBlockAndWait
,这应该永远不会被执行,因为它可能导致死锁。通常,除非你真的知道自己在做什么,否则应该避免使用非异步线程模型。
您的代码应该更像这样。每个performBlock
调用都会将一个块发布到一个消息队列中,该消息队列将独立于任何等待的线程进行处理。
- (void)handleUpdate
{
[self.mainContext performBlock:^{
NSArray *objectIDs = [self.objectsInMainContext valueForKeyPath:@"objectID"];
[self.privateContext performBlock: ^{
// Some processing with objectIDs
}];
});
}