ios - 分派(dispatch)一次 (dispatch_once) 单例在 objective-c 中卡住/锁定

标签 ios objective-c xcode singleton grand-central-dispatch

这行代码在我的 awakeFromFetch 方法中调用,该方法位于实现 NSManagedObject 的自定义托管对象内。这一行特别调用了我的名为 sharedManager 的单例网络管理器类。

[self setSync:(![[WKNetworkManager sharedManager] objectHasPendingRequests:self.objectID]) ];

dispatch_once block 将被命中,如下所示。请注意,它以一种很好的方式实现,如图所示 here :

enter image description here

dispatch_once 调用然后转到 once.h 并在此处卡住在突出显示的行上:

dipatch_once deeper

这是堆栈跟踪:

stack trace

所有这些都发生在尝试加载以前保存的网络队列文件时。该应用程序完全关闭以保存,然后再次启动,然后发生这种卡住/锁定。

我什至尝试按照建议使用此代码来解决问题 here , 但它没有用。但是无论如何改变它可能并不重要,因为我原来的 dispatch_once 代码已经运行了很长时间。只是在这种特殊情况下。

if ([NSThread isMainThread]) 
{
    dispatch_once(&onceToken, ^{
    stack = [[KACoreDataStack alloc] init];});
} 
else 
{
    dispatch_sync(dispatch_get_main_queue(), ^{
    dispatch_once(&onceToken, ^{
    stack = [[KACoreDataStack alloc] init];});
});
}

到目前为止,这些是我解决此类问题的来源:

感谢您的帮助!

最佳答案

该死的 child ,这是一个很好的提问工作。

这里的问题是对 dispatch_once 的递归调用会死锁。如果您需要确切的详细信息,you can find them with the source here .所以你需要重写以避免这种情况。

我的观点是,导致此 -loadQueueFromDisk 调用的任何因素都存在架构失误。您绝对想做任何在执行时间上可能不受限制的事情,就像在 dispatch_once 中关闭并从磁盘加载某些东西一样。你想要做的是创建一个可寻址的单例并退出的绝对最低限度。然后,给它一个“初始化”的内部状态,并将磁盘加载的东西传送到某个地方的非阻塞队列中。这样,所有不依赖于从磁盘加载的东西的东西都可以继续,而所有依赖于从磁盘加载的东西的东西都可以将自己添加到磁盘加载所在的队列中,或者每隔几百毫秒检查一次以查看如果它处于“已初始化”状态,或者类似的状态。

关于ios - 分派(dispatch)一次 (dispatch_once) 单例在 objective-c 中卡住/锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28596305/

相关文章:

objective-c - iOS 设备可以向 Rails 应用程序发送 PUT 请求吗?

ios - 由于错误 "Failed to use existing instance 0 for app with bundle identifier: com.apple.Carousel",Apple Watch 应用无法构建

arrays - 将核心数据库数据提取到数组中

ios - NSOperationQueue的多个分配使我的应用程序崩溃

ios - 尽管 NSAttributedString 不同意,为什么第二个文本 block 的行高比第一个高得多?

iphone - 测试 NSURLConnection 与 HTTP 响应错误状态的使用

objective-c - 将 Google Objective-C API 'GTL' 添加到 iPhone 项目

ios - 无法从我的项目中的框架加载图像

iphone - App delegate 分配的对象显示在多个 subview 中?

ios - 如何关闭 iOS 设备