我正在向用户显示包含一些数据的表格。一旦显示视图,我正在进行Web调用以查看是否有更新的数据(异步)。当服务调用返回时,我想更新我的核心数据和视图。
不幸的是,我经常会死锁,因为视图会读取与服务调用写入相同的数据。我该如何解决这个问题?
当模拟器冻结后暂停模拟器时,等待的线程在以下位置等待:
后台(更新)线程:(psynch_cvwait)
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
主线程:(psynch_mutexwait)
执行filteredArrayUsingPredicate
非常感谢!
答案 0 :(得分:8)
-mergeChangesFromContextDidSaveNotification:
将阻止主线程。该调用将锁定NSManagedObjectContext
个实例,同时更新主要上下文并传入更改。
在iOS 5之前的应用程序中,这通常被认为是不可避免的。您可以通过更频繁,更小的保存来最小化它,但它仍然会发生。
iOS 5之前的应用程序唯一的另一个选择是将主要上下文告诉-reset:
,但这需要重新获取所有内容 - 另一个延迟。
答案 1 :(得分:2)
看起来主线程试图获取后台线程已经拥有的一些低级别锁定(反之亦然)。您是否在某处使用@synchronized
来提供互斥?
无论如何,你的后台线程需要等待-mergeChangesFromContextDidSaveNotification:
完成是否有任何理由?如果没有,请将NO
作为最后一个参数传递。
答案 2 :(得分:0)
当我在主要和背景上下文(使用NSConfinementConcurrencyType
)之间合并上下文更改(两种方式)时,我遇到了同样的问题(锁定psynch_cvwait)。问题是由订阅发送它的其他队列上的NSManagedObjectContextDidSaveNotification
引起的:
[[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextDidSaveNotification
object:mainContext
queue:bgQueue
usingBlock:^(NSNotification * _Nonnull note) {
// bgContext runs on bgQueue
[bgContext mergeChangesFromContextDidSaveNotification:note];
}]
结果从未调用过块,并且psynch_cvwait()
我通过不阻止mainContext的队列来修复它:
[[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextDidSaveNotification
object:mainContext
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
[bgQueue addOperationWithBlock:^{
[bgContext mergeChangesFromContextDidSaveNotification:note];
}];
}]
但是,如果在将更改合并到主要上下文中时阻止后台队列,则似乎不会出现问题。