BLE + Core Data 导致冻结(信号量等待陷阱)

Posted

技术标签:

【中文标题】BLE + Core Data 导致冻结(信号量等待陷阱)【英文标题】:BLE + CoreData causes freeze (semaphore_wait_trap) 【发布时间】:2015-03-06 09:48:15 【问题描述】:

我正在开发一个应用程序,它将通过 CoreBluetooth (BLE) 接收数据并将其与 CoreData 一起存储。它们单独工作得很好,但不能一起工作,我认为这与线程有关。

我做什么

我使用单例来处理 CoreData 交互。单例初始化代码如下。初始化代码基本上是斯坦福课程 CS193p 的复制粘贴。

第一次访问单例是当 CoreBluetooth 从蓝牙外围设备接收到某个数据块时。请参阅下面的代码。

单例初始化

static SessionManager *sharedInstance;

+ (instancetype)sharedSessionManager

    NSLog(@"Shared instance requested.");

    static dispatch_once_t once;
    dispatch_once(&once, ^
        sharedInstance = [[self alloc] init];
     );
     return sharedInstance;

第一次 SessionManager 访问

-(void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error 
    // First some data processing
    ...
    [[SessionManager sharedSessionManager] addMessageToCurrentSession:message];

会发生什么

-(instancetype) init 内部,整个应用程序在下面的行冻结(零 CPU,没有内存增加)。 当断点到达这一点时(即在它执行之前),我还添加了线程的图像。

[self.document openWithCompletionHandler:^(BOOL success) 
    if (success) [self documentIsReady];
    if (!success) NSLog(@"Could not open document %@", [self.documentPath path]);
];

我的问题

发生了什么,我做错了什么?

【问题讨论】:

init 中调用异步方法是个坏主意。无论如何,Singleton 是个坏主意。您应该用普通类替换会话管理器单例并使用依赖注入。然后您可以从init 中删除异步方法 感谢您的评论!我不能只是从init 移动异步吗?例如,我第一次需要访问不在init 的文档。我也从这里获得了灵感,他/她似乎也遵循了类似的方法。 themainthread.com/blog/2012/03/… 是的,你可以使用这种方法,但你应该尝试让自己摆脱单身 嗯,试过了,没用。 :/ 题外话:我知道有很多关于这个的讨论,但是你的不使用单例的论点是什么?在这种情况下,我需要从多个位置与之交互的单个实体(数据库),但我知道要小心使用它们。 您看到的问题是针对 Singletons 的经典案例 - 使用 DI,您可以轻松注入 null 或模拟 SessionManager,以便将 BT 与数据库函数分开测试 【参考方案1】:

您的问题是您的SessionManager 单例初始化存在竞争条件-您的SessionManager init 调用openWithCompletionHandler 异步完成,因此init 在对象实际之前返回 em> 已初始化。

我建议您从 SessionManager 实现一个委托,以便在初始化完成时回调。

【讨论】:

以上是关于BLE + Core Data 导致冻结(信号量等待陷阱)的主要内容,如果未能解决你的问题,请参考以下文章

冻结(挂起)会发生在不使用互斥锁、信号量等的线程不安全代码中吗?

使用 BLE 从智能手表接收加速度计和陀螺仪信号

Android蓝牙BLE我可以修改啥连接的配置参数

iOS Core Data - 意外的内存泄漏

程序接收信号:带有Core Data的“EXC_BAD_ACCESS”

后台线程方法无法解决冻结问题