确保两个计时器的执行逻辑不会同时运行



我有两个以不同时间间隔运行的计时器,其中一个被添加到运行循环中。

let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
// do some stuff
}
let timer2 = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
// do some other stuff
}
RunLoop.current.add(timer2, forMode: RunLoop.Mode.common)

我有一个条件,要求两个计时器的执行逻辑不会同时运行,因为它们都在修改相同的数据结构。

这已经被iOS保证了吗? 如果没有,我能确保这种情况发生的最佳方法是什么?

只要你把计时器安排在同一RunLoop上,你就是安全的。RunLoop始终只与一个线程相关联,因此块将在该线程上执行。因此,它们永远不会同时开火。 但是,如果您将它们安排在两个不同的RunLoop实例上,情况就会有所不同。 我不确定你说一个计时器只添加到RunLoop是什么意思.如果不向RunLoop添加计时器,则根本不会触发。

你的代码不符合你所描述的: APIscheduledTimer(withTimeInterval将计时器隐式添加到运行循环中。您不得自行将计时器添加到运行循环中。 因此,两个计时器都在运行循环上运行。


我建议使用DispatchSourceTimer和自定义DispatchQueue。默认情况下,队列是串行的,并作为 FIFO(先进先出(工作。串行队列保证任务不会同时执行。

计时器在创建后将挂起。您必须调用activate()(或在iOS 9及更低版本中resume()(才能启动计时器,例如在viewDidLoad

class Controller : UIViewController {

let queue = DispatchQueue(label: "myQueue")

lazy var timer1 : DispatchSourceTimer = {
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.schedule(deadline:.now() + 1.0, repeating: 1.0)
timer.setEventHandler(handler: eventHandler1)
return timer
}()


lazy var timer2 : DispatchSourceTimer = {
let timer = DispatchSource.makeTimerSource(queue: queue)
timer.schedule(deadline:.now() + 0.5, repeating: 0.5)
timer.setEventHandler(handler: eventHandler2)
return timer
}()

override func viewDidLoad() {
super.viewDidLoad()
timer1.activate()
timer2.activate()
}

func eventHandler1() {
DispatchQueue.main.async {
// do stuff on the main thread
}
}

func eventHandler2() {
DispatchQueue.main.async {
// do stuff on the main thread
}
}
}

计时器属性被延迟声明以避免可选,事件处理程序闭包(() -> Void(作为标准方法实现。

如果您同时安排两个计时器,则无法确保它们会同时触发。

你可以通过以下方式确保它,在定时器1的火块中安排计时器2,等等...

如果您需要确保计时器块的串行执行,而不管计时器本身被调度在哪里,您应该创建自己的串行队列并将计时器的工作分派到其中:

let timerQueue = DispatchQueue(label: "timerQueue")
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
timerQueue.async {
// do stuff
}
}
let timer2 = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
timerQueue.async {
// do some other stuff
}
}

相关内容

  • 没有找到相关文章

最新更新