NSRunLoop 阻塞传入数据

Posted

技术标签:

【中文标题】NSRunLoop 阻塞传入数据【英文标题】:NSRunLoop blocks incoming data 【发布时间】:2018-03-29 13:55:27 【问题描述】:

我尝试同步使用蓝牙通信。我将数据发送到 BTLE 设备并等待响应以相同的方法继续,除非发生超时。 我想使用 NSRUNLOOP 等待。但是,我有一个问题,只有当循环完成时,才能处理其间接收到的数据。所以循环似乎阻止了数据的处理。 数据在单独的线程中发送

... create command data
if (![self sendCommand:nd_commandData timeOutMesc:ui_timeOutMSec command:ui_command error:error])

    // Timeout
    return false;

... continue working with the received data

超时发送方法:

-(BOOL)sendCommand:(NSData *)nd_sendData timeOutMesc:(uint)ui_timeOutMSec command:(UInt16)ui_command

  b_exitConditionSleep = false;
  b_timeOutOccurred = false;

  self.ni_totalResponseLength = 0;
  self.ni_expectedResponseLength = 0;

  // Clear buffer
  memset(&uia_receivedDataBytes[0], 0x00, sizeof(uia_receivedDataBytes));

  [[BTLE_Communicator sharedInstance] setDelegate:self];

// send data
  [[BTLE_Communicator sharedInstance] sendDataFromAppToBLEDevice:nd_sendData];

  BOOL b_rechTimeOut = true;
  NSDate *start = [NSDate date];
  NSTimeInterval timeInterval;
  uint ui_differenz;
  NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.01];

  while (!b_exitConditionSleep && [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:loopUntil])
  
    loopUntil = [NSDate dateWithTimeIntervalSinceNow:0.01];

    timeInterval = [start timeIntervalSinceNow] * -1;
    ui_differenz = round(timeInterval * 1000);

    if (ui_differenz >= ui_timeOutMSec) 
        NSLog(@"Command: 0x%hX - Timeout reached: %u", ui_command, ui_differenz);
        b_rechTimeOut = false;
        b_timeOutOccurred = true;
        break;
    
  

  return b_rechTimeOut;

接收方式:

-(void)communicatorPeripheralDidReceiveResponseUARTData:(NSData *)nd_data

  NSLog(@"ResponseUARTData %@", nd_data);

  if (!b_timeOutOccurred)
  
    b_exitConditionSleep = true;
    [self processResponseData:nd_data];
  

也许有人指出我做错了什么。

【问题讨论】:

您正试图将一个固有的异步进程转变为一个同步进程。这很少是一个好主意。 【参考方案1】:

我做错了什么

您正在尝试使异步任务同步。这才是核心问题。至于这个特定模式不起作用的具体原因,很可能是嵌套的运行循环阻止了回调被正确处理。或者可能是其他一些实现细节与从异步到同步的转换不兼容。

除了求知欲之外,没有太多理由弄清楚原因。

相反,从communicatorPeripheralDidReceiveResponseUARTData: 的实现中调用某种更新方法。这将允许处理按预期进行异步处理。

【讨论】:

以上是关于NSRunLoop 阻塞传入数据的主要内容,如果未能解决你的问题,请参考以下文章

NSRunLoop-使用场景分析

NSRunLoop-使用场景分析

NSRunLoop的进一步理解

在 NSRunLoop 上调度流

[iOS]浅谈NSRunloop工作原理和相关应用

关于 NSTimer 和 NSRunLoop 的一些理解