Ios 为什么DispatchQueue不尊重QoS?

Ios 为什么DispatchQueue不尊重QoS?,ios,grand-central-dispatch,dispatch-async,Ios,Grand Central Dispatch,Dispatch Async,我试图在主队列上运行多个任务,有些任务比其他任务更紧急。我经常这样做: 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 {

我试图在主队列上运行多个任务,有些任务比其他任务更紧急。我经常这样做:

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)
  }
}
我希望看到五个0,然后是五个-1,然后是五个-2,依此类推

但我得到了:

-十五 -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类,而不是不同的相对优先级:

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?我的目标是在主队列上以较低的优先级运行某些任务。

在WWDC 2016视频中,他们提到,当您向具有较高优先级的队列中添加某些任务时,它不会“跳转队列”,而是使用QoS来解决优先级反转问题(例如,它可以使用它来增加队列中先前任务的优先级,以满足高QoS的后续任务,而不是改变串行队列中任务的顺序)

另外,我建议您不要在主队列中测试这类内容。这是一个带有专用线程的特殊串行队列,因此它对于检查QoS如何影响任务的调度和优先级并不是非常有用。我建议您创建自己的并发队列来测试QoS问题。此外,如果您将任务添加到并发队列中然而,它们通常必须足够丰富,足够多,才能看到任何可识别的模式


最后,我鼓励您观看WWDC 2015视频,因为它更详细地介绍了QoS。上述2016年视频有助于Swift 3的具体观察,但它实际上是建立在2015年视频的QoS讨论基础上的。

解决方案是使用OperationQueue:

let operation = BlockOperation(block: self.doSomething)

operation.queuePriority = .low

OperationQueue.main.addOperation(operation)
然后我可以连续执行低优先级任务,一个接一个,而不会使UI无响应


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

对于案例1,我尝试过,但在控制台中没有打印任何内容Playground@MikeAlter它在操场上不工作。请尝试一个传统的iOS项目。可能是因为此输出是进程,因为在
enqueue
方法中没有长时间运行的任务,请尝试
sleep
方法并再次检查hanks。这很有意义。我将观看那些WWDC会话。请注意,我确实希望使用主队列进行测试,因为我确实希望任务按优先级顺序在主队列上执行。使用其他队列进行测试将不能代表我希望执行的操作。也许我将在DispatchQ上构建自己的层ueue:)QoS不会影响特定串行队列(主队列是串行队列)上项目的顺序。观看这些视频,它应该变得更清晰一些。如果在那之后你仍然有问题,发布一个单独的问题,也许向我们展示你试图解决的更广泛的问题(因为,毫无冒犯之意,在主队列上安排这么多事情的想法(永远不应该被阻止)这样的优先级会产生任何影响,这意味着一个更深层次的设计问题;如果我们知道您试图解决的问题,我们可以给您更好的建议)。明白了。我已经下载了视频,以后再看。我将尝试OperationQueue,它不支持优先级。没有冒犯,我很欣赏你的想法。如果每个任务很快完成,主线程就不会被阻塞:在主队列上执行一个1s长的操作是个问题。每10毫秒100个操作都不是问题,只要这些操作排在更重要的任务后面,比如UI事件。这样,我就可以在没有同步和竞争条件的情况下获得线程的好处。UI在我的测试中保持响应,因此没有问题。我的beta测试人员也没有将此标记为问题。我还记录了阻止主线程的时间,因此我知道情况是否变得更糟。