利用信号量同步蓝牙代理返回的数据

2021-11-04  本文已影响0人  小巧书童

最近公司的项目涉及到了蓝牙开发,在开发的过程中遇到了一个问题,怎么将蓝牙代理方法中异步返回的数据同步出来.

查了一下资料,知道dispatch_semaphore_t(信号量)可以解决这个问题,好了废话不多说,直接上代码:

首先定义一个block来返回蓝牙是否连接成功

typedefvoid(^ConnectBlock)(BOOLisCon);

@property (copy, nonatomic) ConnectBlock connectBlock;//声明属性

-(BOOL)ConnectTheBluetooth {

dispatch_semaphore_t sema = dispatch_semaphore_create(0);

    __block BOOL iscon;

    self.connectBlock= ^(BOOLisCon) {

        iscon = isCon;

        dispatch_semaphore_signal(sema);

    };

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    return iscon;

}

//蓝牙代理方法

//连接到Peripherals-成功

- (void)centralManager:(CBCentralManager*)central didConnectPeripheral:(CBPeripheral*)peripheral {

    // Detect the Bluetooth reader.

    if (self.connectBlock) {

        self.connectBlock(YES);

    }

}

//连接到Peripherals-失败

- (void)centralManager:(CBCentralManager*)central didFailToConnectPeripheral:(CBPeripheral*)peripheral error:(NSError*)error {

 // Show the error

 if(error !=nil) {

       if(self.connectBlock) {

            self.connectBlock(NO);

    }

    }

}

但是,在代码运行的时候发现根本就不走block里面的方法,线程直接卡住了,这就很难受了,没办法只有继续摸索了,后来查了一下资料才发现问题出在了蓝牙初始化方法:

_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

初始化蓝牙的时候queue填的nil,默认是主线程

外部在调用- (BOOL)ConnectTheBluetooth方法的时候,创建的总信号量为0,代码执行到代码执行到dispatch_semaphore_wait时, 主线程阻塞,直到收到信号才会往下继续执行;

dispatch_semaphore_signal(s)发送信号是放在主线程中执行,由于此时主线程是阻塞的,那么dispatch_semaphore_signal(s)不会执行,这形成了死锁的情况。

所以正确的做法是开辟一个线程来初始化蓝牙,

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:queue];

这样蓝牙的代理方法在子线程中进行,外部调用- (BOOL)ConnectTheBluetooth方法的时候,主线程卡在dispatch_semaphore_wait时,子线程还在走,走到蓝牙的代理方法中,执行block回调方法:

 self.connectBlock= ^(BOOLisCon) {

       dispatch_semaphore_signal(sema);

    };

dispatch_semaphore_signal(s)发送信号,使主线程继续执行,这样就可以实现同步代理返回的数据了.

上一篇 下一篇

猜你喜欢

热点阅读