如何退出 [NSRunLoop runUntilDate]?

发布于 2024-08-17 07:57:39 字数 996 浏览 6 评论 0原文

我正在编写一个应用程序,它必须与通过 USB 连接的设备进行通信。该应用程序按固定时间轮流从设备发送和接收数据。所有 Rx/Tx 都发生在单独的线程中,否则 UI 将被阻塞。基本结构基本上是这样的。 (自动释放池和省略的内容)

-(void)comThread:(id)arg {
  while(state == kIsConnected) {
    // let timers run
    [runLoop runUntilDate:[NSDate distantFuture]];
    // handle data
    if(rxTxState == kRx) {
      // do some stuff to pass data to upper layers
      rxTxState = kTx;
    }
    if(rxTxState == kTx) {
      // do some stuff to send data
      rxTimeoutTimer = [NSTimer scheduledTimer....];
    }
  } 
}

发送数据后,应用程序等待接收数据或触发 rxTimeoutTimer ,这会导致数据包重新传输。 rx 操作之所以有效,是因为底层使用异步系统调用并调用 rx 处理程序,其基本上如下所示。

-(void)receiveData:(NSData*)data{
  [rxQueue addObject:data];
  [rxTimeoutTimer invalidate];  // cancel timeout
}

有没有一种(简单)方法可以使 [runLoop runUntilDate:]receiveData: 退出? Apple 文档表示,删除所有计时器源并不能保证 RunLoop 退出。我读到了一些关于调用 performSelector:onThread:... 的内容,但它要么不起作用,要么我没有明白这一点。

谢谢。

I am writing an application which has to communicate with a device connected via USB. The app sends and receives data in turns from the device on a fixed timing. All Rx/Tx happens in a separate thread because otherwise the UI would be blocked. The basic structure looks basically like this. (autorelease pools and stuff omitted)

-(void)comThread:(id)arg {
  while(state == kIsConnected) {
    // let timers run
    [runLoop runUntilDate:[NSDate distantFuture]];
    // handle data
    if(rxTxState == kRx) {
      // do some stuff to pass data to upper layers
      rxTxState = kTx;
    }
    if(rxTxState == kTx) {
      // do some stuff to send data
      rxTimeoutTimer = [NSTimer scheduledTimer....];
    }
  } 
}

After sending data, the app waits for either data to be received or the rxTimeoutTimer to fire which leads to retransmission of the packet. The rx-operation works since the underlying layers use async system calls and calls a rx-handler which look basically like this.

-(void)receiveData:(NSData*)data{
  [rxQueue addObject:data];
  [rxTimeoutTimer invalidate];  // cancel timeout
}

Is there an (easy) way to make the [runLoop runUntilDate:] exit from receiveData:? The Apple docs say that removing all timer sources does not guarantee the RunLoop to exit. I read something about calling performSelector:onThread:... but it either did not work or I did not get the point.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蹲墙角沉默 2024-08-24 07:57:39
CFRunLoopStop([runLoop getCFRunLoop]);
CFRunLoopStop([runLoop getCFRunLoop]);
空宴 2024-08-24 07:57:39

标准模式是运行 runloop 一段超时时间(例如 0.5 秒),然后迭代直到任务完成:

while(state == kIsConnected) {
  while(!iterationDone) {
    [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
    //do other stufff
  }
}

-(void)receiveData:(NSData*)data{
  [rxQueue addObject:data];
  [rxTimeoutTimer invalidate];  // cancel timeout
  iterationDone = YES;
}

The standard pattern is to run the runloop for some timeout period (e.g. 0.5 seconds), and then iterate until the task is accomplished:

while(state == kIsConnected) {
  while(!iterationDone) {
    [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
    //do other stufff
  }
}

-(void)receiveData:(NSData*)data{
  [rxQueue addObject:data];
  [rxTimeoutTimer invalidate];  // cancel timeout
  iterationDone = YES;
}
热风软妹 2024-08-24 07:57:39

CFRunLoopStop([runLoop getCFRunLoop]);

取消执行选择器

对我不起作用,
请参阅我的运行代码 [NSRunLoop currentRunLoop]

timerUpdateLocation = [NSTimer scheduledTimerWithTimeInterval:[time intValue] target:self selector:@selector(startTrackingBg) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timerUpdateLocation forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];

要停止它,我只需使计时器无效。

[timerUpdateLocation 无效];

CFRunLoopStop([runLoop getCFRunLoop]);
and
CancelPerformSelector

didnot work for me ,
See my Code for running [NSRunLoop currentRunLoop]

timerUpdateLocation = [NSTimer scheduledTimerWithTimeInterval:[time intValue] target:self selector:@selector(startTrackingBg) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timerUpdateLocation forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];

To Stop it I Just invalidate timer.

[timerUpdateLocation invalidate];

余生再见 2024-08-24 07:57:39

这样做就可以退出了。但几秒钟后就会退出。

 -(void)comThread:(id)arg {
      BOOL ret = YES;
      rxTimeoutTimer = [NSTimer scheduledTimer....];
      while(ret) {
        // let timers run
        ret = [runLoop runUntilDate:[NSDate distantFuture]];
      } 
    }
    -(void)receiveData:(NSData*)data{
      [rxQueue addObject:data];
      [rxTimeoutTimer invalidate];  // cancel timeout
      iterationDone = YES;
    }

kennytm 的答案似乎是正确的。

Do like this can exit. but it will exit after a few seconds.

 -(void)comThread:(id)arg {
      BOOL ret = YES;
      rxTimeoutTimer = [NSTimer scheduledTimer....];
      while(ret) {
        // let timers run
        ret = [runLoop runUntilDate:[NSDate distantFuture]];
      } 
    }
    -(void)receiveData:(NSData*)data{
      [rxQueue addObject:data];
      [rxTimeoutTimer invalidate];  // cancel timeout
      iterationDone = YES;
    }

the kennytm's answer seems right.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文