我必须定期(每 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/