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

标签 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

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

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

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

谢谢。

最佳答案

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 能够在后台线程上执行,请使用全局队列而不是主队列。

dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)

不过,即使使用全局队列也可能不稳定。我认为 CADisplayLink 更稳定。

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

关于iPhone - 关于调度计时器和计时的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5748700/

相关文章:

ios - 无法使用以下代码更新记录

ios - Swift:从 iOS 7 编译存档时出现段错误

iphone - 检测 dispatch_async 方法是否仍在运行

ios - iOS 上的 Xamarin.Forms AbsoluteLayout 问题

iOS 8 - 以横向模式启动应用程序

ios - dispatch_sync和dispatch_main有什么区别?

ios - 如何使用 GCD 说明后台任务?

ios - 无法使用类型的参数列表调用 'dispatch_once'

iphone - 如何从触摸事件中获取信息?

iphone - iOS 游戏是如何设置的?