为什么DispatchQueue不尊重QoS?

时间:2017-09-08 06:24:49

标签: ios grand-central-dispatch dispatch-async

我试图在主队列上运行多个任务,其中一些比其他任务更紧急。我使用DispatchQoS执行此操作:

func enqueue(_ prio: Int) {
  let qos = DispatchQoS(qosClass: .userInteractive, relativePriority: prio)
  DispatchQueue.main.async(qos: qos) {
    NSLog("\(prio)")
  }
}

for i in 1...5 {
  for prio in -15...0 {
    enqueue(prio)
  }
}

我希望看到五个零,然后是五个-1,然后是五个-2,依此类推。

但我得到了:

-15  -14  -13  -12  -11  -10  -9  -8  -7  -6  -5  -4  -3  -2  -1  0  -15  -14  -13  -12  -11  -10  -9  -8  -7  -6  -5  -4  -3  -2  -1  0  -15  -14  -13  -12  -11  -10  -9  -8  -7  -6  -5  -4  -3  -2  -1  0  -15  -14  -13  -12  -11  -10  -9  -8  -7  -6  -5  -4  -3  -2  -1  0  -15  -14  -13  -12  -11  -10  -9  -8  -7  -6  -5  -4  -3  -2  -1  0

换句话说,调度队列按照他们排队的顺序执行任务,忽略优先级。

然后我尝试了不同的QoS类而不是不同的relativePriority:

func enqueue(_ qos: DispatchQoS) {
  DispatchQueue.main.async(qos: qos) {
    NSLog("\(qos.qosClass)")
  }
}

for i in 1...10 {
  enqueue(.background)
  enqueue(.utility)
  enqueue(.userInitiated)
  enqueue(.userInteractive)
}

但是这些任务再次按入队顺序执行,忽略了QoS。

如何让调度队列尊重QoS?我的目标是在主队列上运行一些优先级低于其他任务的任务。

2 个答案:

答案 0 :(得分:2)

在WWDC 2016视频Concurrent Programming with GCD in Swift 3中,他们提到当您向具有更高优先级的队列添加内容时,它不会“跳过队列”,而是使用QoS来解析优先级倒置(例如可以使用它来增加队列中先前任务的优先级,以满足高QoS后续任务,而不是改变串行队列中任务的顺序。)

另外,我建议你不要用主队列测试这种东西。这是一个带有专用线程的特殊串行队列,因此对于检查QoS如何影响任务的调度和优先级并不是非常有用。我建议创建自己的并发队列来测试QoS问题。此外,如果您向并发队列添加任务,它们通常必须足够实用且足够多,以查看任何可辨别的模式。

最后,我建议您观看WWDC 2015视频Building Responsive and Efficient Apps with GCD,因为它会更详细地介绍QoS。上述2016年视频适用于Swift 3特定观测,但它确实建立在2015年视频的QoS讨论基础之上。

答案 1 :(得分:1)

解决方案原来是使用OperationQueue:

 cout << setw(10) << i
      << setw(10) << std::to_string(i) + ch;

然后我可以一个接一个地继续执行低优先级任务,而不会使UI无响应。

感谢Rob指出为什么DispatchQueues不尊重优先事项。