Как выйти из [NSRunLoop runUntilDate]? - PullRequest
3 голосов
/ 11 января 2010

Я пишу приложение, которое должно взаимодействовать с устройством, подключенным через USB. Приложение отправляет и получает данные по очереди от устройства в фиксированное время. Все Rx / Tx происходит в отдельном потоке, потому что в противном случае пользовательский интерфейс был бы заблокирован. Основная структура выглядит в основном так. (автозапуск бассейнов и прочее пропущено)

-(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 работает, так как нижележащие слои используют системные вызовы async и вызывают обработчик rx, который выглядит в основном так.

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

Есть ли (простой) способ сделать [runLoop runUntilDate:] выход из receiveData:? Документы Apple говорят, что удаление всех источников таймера не гарантирует выхода из RunLoop. Я что-то читал о звонке performSelector:onThread:..., но он либо не работал, либо я не понял смысла.

Спасибо.

Ответы [ 4 ]

9 голосов
/ 12 января 2010
CFRunLoopStop([runLoop getCFRunLoop]);
4 голосов
/ 12 января 2010

Стандартный шаблон - запустить цикл запуска в течение некоторого периода времени ожидания (например, 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;
}
0 голосов
/ 14 декабря 2015

Как это может выйти.но он выйдет через несколько секунд.

 -(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;
    }

ответ Кеннимма кажется правильным.

0 голосов
/ 22 сентября 2014

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];

...