2014-12-16 2 views
3

У меня есть таймер, сгенерированный за 5 секунд, добавленный в глобальную очередь, хотя я недействителен после 2-секундного цикла цикла, который не заканчивается до 5 секунд. В следующем фрагменте backgroundTimer является экземпляром var, а run - это функция-член. Что не так в следующем коде, который блокирует завершение цикла цикла.Как удалить таймер из runloop немедленно

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    _backgroundTimer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(run) userInfo:nil repeats:NO]; 
    [ [NSRunLoop currentRunLoop] addTimer:_backgroundTimer forMode:NSRunLoopCommonModes]; 
    [[NSRunLoop currentRunLoop] run]; 

    NSLog(@"Run loop terminated"); 

}); 

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [_backgroundTimer invalidate]; 
    _backgroundTimer=nil; 

}); 
+0

даже попытался добавить CFRunLoopStop ([[NSRunLoop currentRunLoop] getCFRunLoop]); после недействительности, – pradeepa

ответ

3

Первая проблема здесь состоит в том, что таймер добавляется в цикл выполнения на некотором произвольном фоновом потоке. (т. е. поток будет создан GCD для обслуживания фоновой очереди). Вы можете это сделать, но это не имеет никакого смысла.

Именно в сторону, вы сказали, что вы хотите, чтобы произошло для этого цикла запуска, чтобы выйти, но в документации по методу -run, он говорит следующее:

Ручное удаление всех известных источников входного сигнала и таймеры из цикла запуска не являются гарантией завершения цикла выполнения. OS X может установить, и удаляет дополнительные источники входных данных, если необходимо, для обработки запросов, направленных по адресу в потоке получателя. Таким образом, эти источники могут помешать выходу цикла .

Если вы хотите, чтобы цикл цикла завершился, вы не должны использовать этот метод. Вместо этого используйте один из других способов запуска, а также проверьте произвольные произвольные условия в петле.

Вы должны будете сами вращать цикл событий, если вы хотите выйти из него, когда таймер недействителен. Например:

while (_backgroundTimer.valid && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]); 

Это приведет к выходу из цикла выполнения максимум 0,1 (- эпсилон) секунд после того, таймер будет отменен.

0

Попробуйте так:

[NSRunLoop cancelPreviousPerformRequestsWithTarget:self selector:@selector(run) object:nil]; 

Отредактировано:

-(void)run{ 
    if(taskComplete){ 
     [_backgroundtimer invalidate]; 
} 
+0

попробовал, он не работал, я думаю, cancelPreviousPerformRequestsWithTarget отменит только те, которые запланированы с использованием семейства методов performSelector. – pradeepa

+0

Мне нужно выйти из runloop перед вызовом run, а не в течение 1-й итерации для запуска метода, но во время последующей итерации. – pradeepa

+0

@pradeepa ваш код отлично работает, вы проверили его правильно? Он выходит из таймера перед вызовом метода запуска. – cyberlobe

Смежные вопросы