Обеспечение того, чтобы лог c двух таймеров не запускался одновременно - PullRequest
1 голос
/ 18 июня 2020
• 1000 таймеры не работают одновременно, поскольку они оба изменяют одни и те же структуры данных.

Это уже гарантировано iOS? Если нет, как лучше всего добиться этого?

Ответы [ 4 ]

2 голосов
/ 21 июня 2020

Ваш код не соответствует тому, что вы описываете: API scheduledTimer(withTimeInterval неявно добавляет таймер к runl oop. Вы не должны самостоятельно добавлять таймер в runl oop. Итак, оба таймера работают на runl oop.

Рекомендую использовать DispatchSourceTimer и кастом DispatchQueue. Очередь по умолчанию является последовательной и работает как FIFO (первым пришел - первым вышел). Последовательная очередь гарантирует, что задачи не будут выполняться одновременно.

Таймеры приостанавливаются после создания. Вы должны вызвать activate() (или resume() в iOS 9 и ниже), чтобы запустить таймеры, например, в 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) реализовано как стандартные методы.

2 голосов
/ 18 июня 2020

Пока вы планируете таймеры на одном и том же RunLoop, вы в безопасности. A RunLoop всегда связан ровно с одним потоком, поэтому блоки будут выполняться в этом потоке. Следовательно, они никогда не будут стрелять в одно и то же время. Однако все будет по-другому, если вы запланируете их на двух разных RunLoop экземплярах. Я не уверен, что вы имеете в виду, когда говорите, что к RunLoop добавляется только один таймер. Если вы не добавите таймер к RunLoop, он вообще не сработает.

0 голосов
/ 21 июня 2020

Если вам нужно обеспечить последовательное выполнение блоков таймера независимо от того, где были запланированы сами таймеры, вы должны создать свою собственную последовательную очередь и направить работу своего таймера в нее:

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
    }
}

0 голосов
/ 18 июня 2020

Если вы запланируете оба таймера, ничто не гарантирует, что они сработают одновременно.

Вы можете убедиться в этом, запланировав таймер 2 в пожарном блоке таймера 1 и так далее ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...