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