Swift2 dispatch_get_main_queue()不';无法顺利运行新的异步作业 let dispatchGroup=dispatch\u group\u create() 让我们现在就开始行动 对于0中的i..

Swift2 dispatch_get_main_queue()不';无法顺利运行新的异步作业 let dispatchGroup=dispatch\u group\u create() 让我们现在就开始行动 对于0中的i..,swift2,grand-central-dispatch,tvos,dispatch-after,Swift2,Grand Central Dispatch,Tvos,Dispatch After,问题不是dispatch\u get\u main\u queue()。(如果使用不同的队列,您会注意到相同的行为。)问题在于dispatch\u after() 当您在之后使用dispatch\u时,它会创建一个调度计时器,当启动时,该计时器的剩余时间为启动时间的10%。看看苹果github。净效应是,当这些计时器(开始±10%回旋余地)重叠时,可能会开始合并它们。当它们结合在一起时,它们会以“聚集”的方式发射,一束接着一束地发射,然后在到达下一束之前稍有延迟 有两种解决方案,都需要在调用后退

问题不是
dispatch\u get\u main\u queue()
。(如果使用不同的队列,您会注意到相同的行为。)问题在于
dispatch\u after()

当您在之后使用
dispatch\u时,它会创建一个调度计时器,当
启动时,该计时器的剩余时间为
启动时间的10%。看看苹果github。净效应是,当这些计时器(
开始
±10%
回旋余地
)重叠时,可能会开始合并它们。当它们结合在一起时,它们会以“聚集”的方式发射,一束接着一束地发射,然后在到达下一束之前稍有延迟

有两种解决方案,都需要在调用后退出一系列
dispatch\u:

  • 您可以手动构建计时器,强制
    DispatchSource.TimerFlag.strict
    禁用合并:

    let dispatchGroup = dispatch_group_create()
    let now = DISPATCH_TIME_NOW
    
    for i in 0..<1000 {
        dispatch_group_enter(dispatchGroup)
    
        // Do some async tasks
        let delay = dispatch_time(now, Int64(Double(i) * 0.1 * Double(NSEC_PER_SEC)))
    
        dispatch_after(delay, dispatch_get_main_queue(), {
            print(i)
            dispatch_group_leave(dispatchGroup)
        })
    }
    
  • 这不仅解决了合并问题,而且效率更高

    有关Swift 2.3格式副本,请参见

     let group = DispatchGroup()
     let queue = DispatchQueue.main
    
     let start = CACurrentMediaTime()
    
     os_log("start")
    
     for i in 0 ..< 1000 {
         group.enter()
    
         let timer = DispatchSource.makeTimerSource(flags: .strict, queue: queue) // use `.strict` to avoid coalescing
         timer.setEventHandler {
             timer.cancel()       // reference timer so it has strong reference until the handler is called
             os_log("%d", i)
             group.leave()
         }
         timer.schedule(deadline: .now() + Double(i) * 0.1)
         timer.resume()
     }
    
     group.notify(queue: .main) {
         let elapsed = CACurrentMediaTime() - start
         os_log("all done %.1f", elapsed)
     }
    
     var timer: DispatchSourceTimer?    // note this is property to make sure we keep strong reference 
    
     func startTimer() {
         let queue = DispatchQueue.main
    
         let start = CACurrentMediaTime()
    
         var counter = 0
    
         // Do some async tasks
    
         timer = DispatchSource.makeTimerSource(flags: .strict, queue: queue)
         timer!.setEventHandler { [weak self] in
             guard counter < 1000 else {
                 self?.timer?.cancel()
                 self?.timer = nil
                 let elapsed = CACurrentMediaTime() - start
                 os_log("all done %.1f", elapsed)
                 return
             }
             os_log("%d", counter)
             counter += 1
         }
         timer!.schedule(deadline: .now(), repeating: 0.05)
         timer!.resume()
     }