【问题标题】:Proper way to do polling in swift?快速进行轮询的正确方法?
【发布时间】:2017-06-05 11:32:19
【问题描述】:

我对其他编程语言有很多经验,但在 swift 3 方面没有那么多经验。我想做轮询循环。这是我写的:

DispatchQueue.global(qos: .userInitiated).async {
            [unowned self] in
            while self.isRunning {
                WebService.getPeople(completion: nil)
                sleep(100)
            }
        }

这对我来说很好,每 100 秒,我做一次轮询,然后让这个线程休眠。我想知道,这是在 swift 3 中执行此操作的正确方法吗?

【问题讨论】:

  • 首先,尽可能不要。但如果必须,只需使用 Timer
  • 作为一般规则,如果可以避免,请不要长时间阻塞调度线程。
  • @JeremyP 我听别人说同样的话,但我不明白为什么?如果我在一些低优先级的后台线程上调度,那会造成什么麻烦?
  • 使用 GCD,队列上的任务从池中分配线程,该池由操作系统根据 CPU 数量等因素计算得出。当原始任务处于休眠状态时,该线程不能重新分配给另一个调度队列任务。

标签: swift grand-central-dispatch polling


【解决方案1】:

你有两个选择:

  • 使用NSTimer
  • 使用DispatchSourceTimer

使用NSTimer 非常简单,但它需要一个活动的运行循环,所以如果你需要在后台线程上轮询,事情可能会有点棘手,因为你需要创建一个线程并保持运行在其上循环(可能计时器本身将使运行循环保持活动状态)。
另一方面,DispatchSourceTimer 使用queues 工作。您可以轻松地从系统提供的队列之一创建调度源计时器或创建一个。

    var timer: DispatchSourceTimer?
    let queue = DispatchQueue.global(qos: .background)
    guard let timer = DispatchSource.makeTimerSource(queue: queue) else { return }
    timer.scheduleRepeating(deadline: .now(), interval: .seconds(100), leeway: .seconds(1))
    timer.setEventHandler(handler: { 
        // Your code
    })
    timer.resume()

leeway 参数是系统可以延迟计时器的时间量。

【讨论】:

    【解决方案2】:

    Swift 5、iOS 10.0+

    已接受答案中的代码不再编译,可以修改(并简化!)为:

    DispatchQueue.global(qos: .userInitiated).async {
        let timer = Timer.scheduledTimer(withTimeInterval: 100, repeats: true) { timer in
            // Your action
        }
        timer.fire()
    }
    

    【讨论】:

      【解决方案3】:

      斯威夫特 4 和斯威夫特 5

       var timer: Timer? //declare outside function scope
       var runCount = 0
      
      
       self.timer = Timer(timeInterval: 2.0, target: self, selector: #selector(self.fireTimer), userInfo: nil, repeats: true)
      
       guard let timer = self.timer else {return}
       RunLoop.main.add(self.timer, forMode: RunLoop.Mode.default)
      
       @objc func fireTimer() {
               print("Timer fired! \(runCount)")
              runCount += 1
      
              if runCount == 5 {
                  timer?.invalidate() //stop the timer
              }
          }
      

      self.timer = Timer.init(timeInterval: 1.0, repeats: true, block: { (timer) in
              print("\n--------------------TIMER FIRED--------------\n")
              runCount += 1
              if runCount == 5{
                timer.invalidate()
          }
          })
      guard let timer = self.timer else {return}
      
      RunLoop.main.add(self.timer!, forMode: RunLoopMode.defaultRunLoopMode)
      

      【讨论】:

        猜你喜欢
        • 2013-04-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-20
        相关资源
        最近更新 更多