2014-11-03 5 views
0

Я столкнулся с каким-то странным поведением Grand Central Dispatch timer. Он прерывает свой период стрельбы и замерзает в течение многих секунд. Хотя мне нужно пинговать мой сервер, чтобы оставаться «онлайн», это поведение сильно непригодно.Поведение Strange GCD-Timer

Здесь код создания таймера.

// pingTimer and pingQueue are class members 
- (void)createPingTimerSource 
    { 
    // check timer exists 
    if(pingTimer) 
    { 
     // suspend source and cancel 
     [self setPingTimerSuspended:YES]; 
     dispatch_source_cancel(pingTimer); 
    } 
    // check having queue, create if doesn't exist 
    if(!pingQueue) 
     pingQueue = dispatch_queue_create(kDispatchTimerQueueLabel, NULL); 
    // create timer dispatch source 
    pingTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, pingQueue); 
    dispatch_source_set_timer(pingTimer, dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_MSEC), 5*NSEC_PER_MSEC, NSEC_PER_SEC/10); 
    // set event handler 
    dispatch_source_set_event_handler(pingTimer,^{ 
     printf("[%llu] gcd timer fired.\n", mach_absolute_time()/NSEC_PER_SEC); 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     [self sendPingToServer]; 
     }); 
    }); 
    // set cancel handler 
    dispatch_source_set_cancel_handler(pingTimer, ^{ 
     // release dispatch source if exists 
     if(pingTimer) 
     dispatch_release(pingTimer); 
     // check timer queue exists and release if does 
     if(pingQueue) 
     dispatch_release(pingQueue); 
    }); 
    } 

Здесь бревенчатая консоль снята.

Debug console content

Спасибо за помощь.

ответ

1

Несколько возможностей:

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

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

  2. Если ваше приложение не находится на переднем плане, функция «App Nap» может попытаться объединить таймеры, чтобы минимизировать утечку энергии. Таким образом, таймеры могут не вызываться с частотой, которую вы ожидали.

    Вы можете сказать, таймер, чтобы не участвовать путем подачи DISPATCH_TIMER_STRICT в качестве третьего параметра dispatch_source_create, хотя это, очевидно, не рекомендуется, если не абсолютно необходимо (например, взаимодействие с аппаратными средствами, которые не могут допустить отклонения таймера), как вы теряете экономию энергии App Nap обеспечивает.

    См. WWDC 2013 video Improving Power Efficiency with App Nap.

+0

Да, вы правы. Спасибо за помощь! – Astoria

1

dispatch_queue_create не гарантирует, что он создает независимую нить для обработки блоков.

Вот цитата из Apple documentation
Очереди не связаны с какой-либо конкретной темой исполнения и блоками, представленных в независимые очереди могут выполняться одновременно.

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

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