如何退出[NSRunLoop runUntilDate]?

时间:2010-01-11 20:55:41

标签: cocoa macos nsthread nsrunloop

我正在编写一个必须与通过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:...的内容,但它要么不起作用,要么我没有明白这一点。

感谢。

4 个答案:

答案 0 :(得分:9)

CFRunLoopStop([runLoop getCFRunLoop]);

答案 1 :(得分:4)

标准模式是运行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;
}

答案 2 :(得分:0)

  

CFRunLoopStop([runLoop getCFRunLoop]);   和   CancelPerformSelector

对我不起作用, 请参阅我的代码以运行[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 invalidate];

答案 3 :(得分:0)

这样可以退出。但它会在几秒钟后退出。

 -(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的答案似乎是正确的。