iPhone - 关于调度计时器和时间的问题

时间:2011-04-21 19:13:55

标签: iphone ios grand-central-dispatch

我必须定期(每0.16秒)发射一次方法。容差可以说,高达30%。接近16毫秒,更好。

我已经尝试过NSTimers,但它们不够精确。我尝试了线程,也遇到了同样的问题。我正在尝试派遣计时器。

我使用的是Apple提供的代码:

dispatch_source_t CreateDispatchTimer(uint64_t interval,
              uint64_t leeway,
              dispatch_queue_t queue,
              dispatch_block_t block)
{
   dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
                                                     0, 0, queue);
   if (timer)
   {
      dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
      dispatch_source_set_event_handler(timer, block);
      dispatch_resume(timer);
   }
   return timer;
}

void MyCreateTimer()
{
   dispatch_source_t aTimer = CreateDispatchTimer(0.16 * NSEC_PER_SEC, //0.16 ms
                               0.048 * NSEC_PER_SEC, //30% tolerance
                               dispatch_get_main_queue(),
                               ^{ MyPeriodicTask(); });

   // Store it somewhere for later use.
    if (aTimer)
    {
        MyStoreTimer(aTimer);
    }
}

我正在测量间隔并在执行MyPeriodicTask()之间获得这些时间:

0.148,  0.165,  0.148,  0.167,  0.167,  0.187,  0.167,  
0.167,  0.146,  0.166,  0.167,  0.167,  0.188,  0.145,  
0.243,  0.331,  0.047,  0.045,  0.168,  0.165,  0.167, 
0.166,  0.167,  0.167,  0.169,  0.165,  0.166,  0.169,  
0.165,  0.203,  0.130,  0.167,  0.167,  0.167,  0.167,  
0.167,  0.167,  0.167,  0.167,  0.167

请注意,该方法在16ms范围内或多或少地被触发。

考虑到30%的范围,我预计值在0.118和0.214毫秒之间,但注意值远远高于该范围的0.243和0.331以及其他如0.047和0.045!该方法如何在定时器间隔之前触发???

可能发生什么?有没有办法在iPhone上精确执行定时方法???

感谢。

1 个答案:

答案 0 :(得分:6)

dispatch_source_t aTimer = CreateDispatchTimer(0.16 * NSEC_PER_SEC, //0.16 ms
                           0.048 * NSEC_PER_SEC, //30% tolerance
                           dispatch_get_main_queue(),
                           ^{ MyPeriodicTask(); });

您正在使用主队列来触发该功能。这意味着该函数是从主线程上的RunLoop执行的。执行时间取决于RunLoop的任务。如果MyPeriodicTask能够在后台线程上执行,请使用Global Queue而不是Main Queue。

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)

尽管如此,即使使用Global Queue,它也可能不稳定。我认为CADisplayLink更稳定。

幸运的是,CADisplayLink的帧速率在iOS上为60fps。它等于你想要的16.6ms。