如何使用GCD定期在后台运行代码块?

时间:2011-12-18 13:35:38

标签: iphone ios grand-central-dispatch

如何使用GCD定期在后台运行代码块? 我正在尝试编写一个带有几个子系统的游戏引擎,如渲染,物理,游戏逻辑等。有些任务应该是事件驱动的,但是有些任务(比如物理系统)应该在后台以恒定时间周期性地调用(例如在1/100秒之后)。 我创建了一个代码块,但是如何在后台定期运行此块? GCD是正确的工具吗?

3 个答案:

答案 0 :(得分:10)

您想要的是GCD调度源。有关示例代码,请参阅Creating a Timer Example

答案 1 :(得分:6)

正如@matt在评论中指出的那样,您可以使用计时器调度源。看看他在那里找到正确方法的答案。

对于后人来说,这是我原来的答案,有一些选择:

  1. 在渲染回调中(例如,使用CADisplayLink),触发计算此(或下一个?)帧的物理的GCD作业。如果您需要为每个渲染帧执行多次更新,只需将该作业循环几次。

  2. 让物理线程自我休眠,直到下次需要进行一些计算。如果你有一个单独的线程,NSTimer可能有足够的分辨率来唤醒你的线程在100赫兹。 (在主线程上,这不起作用,因为runloop上的其他输入源将阻止它以一致的速度快速触发。)如果NSTimer不起作用,只需计算在您需要的下一次物理更新之前剩余的时间和睡觉你的线程(例如,通过[NSThread sleepForTimeInterval:]

  3. 拥有一个使用dispatch_after

  4. 的区块

    这样的事情:

    dispatch_time_t next = dispatch_time(DISPATCH_TIME_NOW, 0);
    block = ^{
        next = dispatch_time(next, 10000000L); // increment by 10 ms
        // do physics here
        dispatch_after(next, queue, block);
    }
    

    你可能需要更聪明地删除帧,(例如,在调用dispatch_之后检测你的下一次是否过去等等)

答案 2 :(得分:3)

在Swift中你可以使用GCD创建计时器:

func CreateTimerDispatchSource(interval: UInt64, leeway: UInt64, queue: dispatch_queue_t, block: dispatch_block_t) -> dispatch_source_t {
    let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
    dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), interval, leeway)
    dispatch_source_set_event_handler(timer, block)
    return timer;
}

var timer = CreateTimerDispatchSource(5*NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
  // do some serious stuff
}

启动或恢复计时器:

dispatch_resume(timer)

暂停计时器:

dispatch_suspend(timer)