问题
The OperationQueue
documentation states for the qualityOfService
property:
This property specifies the service level applied to operation
objects added to the queue
However one can simply check that this is not true by just copy & pasting the code below into a new playground.
import Foundation
let q = OperationQueue()
q.qualityOfService = .userInitiated
print("QUEUE", q.qualityOfService.rawValue)
let op = BlockOperation()
op.addExecutionBlock {
print("OP", op.qualityOfService.rawValue)
}
q.addOperations([op], waitUntilFinished: true)
You will see that the queues QoS level is 25
/.userInitiated
and the operations -1
/.default
.
So does it mean that the operations QoS level is .default
in relation to the queues elevanted .userInitiated
level, or is it .default
, despite the queue having a higher QoS level?
What I actually expect is that these 2 values should be the same.
PS: I need to invoke a Process
inside the Operation
, which in turn also has a qualityOfService
setting that should be the same as the queue/ops.
回答1:
The operation’s qualityOfService
indicates whether the operation, itself, needs to dictate a particular QoS. But -1
/.default
effectively means that it will just use the QoS for the queue (and thus that of the worker thread that is used). I would not be terribly concerned about the QoS of the operation. What you care about is the QoS of the thread on which it runs:
let q = OperationQueue()
q.qualityOfService = .userInitiated
print("CURRENT", Thread.current.qualityOfService.rawValue) // CURRENT 33
print("QUEUE", q.qualityOfService.rawValue) // QUEUE 25
let op = BlockOperation {
print("THREAD", Thread.current.qualityOfService.rawValue) // THREAD 25
}
q.addOperations([op], waitUntilFinished: false)
As you can see, the QoS for the thread that is running the code is precisely what you would expect it to be.
If you want, you can see how changing the operation’s QoS to something higher than the queue will affect the QoS of the worker thread upon which it runs. Thus, background QoS queue with no QoS specified for the operation:
let q = OperationQueue()
q.qualityOfService = .background
print("CURRENT", Thread.current.qualityOfService.rawValue) // CURRENT 33
print("QUEUE", q.qualityOfService.rawValue) // QUEUE 9
let op = BlockOperation()
op.addExecutionBlock {
print("OP", op.qualityOfService.rawValue) // OP -1
print("THREAD", Thread.current.qualityOfService.rawValue) // THREAD 9
}
q.addOperations([op], waitUntilFinished: false)
But you can, if you want, specify a particular QoS for the operation, in this case escalating it to a higher QoS:
let q = OperationQueue()
q.qualityOfService = .background
print("CURRENT", Thread.current.qualityOfService.rawValue) // CURRENT 33
print("QUEUE", q.qualityOfService.rawValue) // QUEUE 9
let op = BlockOperation()
op.qualityOfService = .userInitiated // change op’s QoS, and thus the worker thread to a higher QoS, too
op.addExecutionBlock {
print("OP", op.qualityOfService.rawValue) // OP 25
print("THREAD", Thread.current.qualityOfService.rawValue) // THREAD 25
}
q.addOperations([op], waitUntilFinished: false)
回答2:
There is documentation about the operation's inference of QoS from the queue (Section "Quality of Service Inference and Promotion").
The particular case of yours is described there as:
Any of the queue’s operations with a lower QoS are promoted to the higher QoS. Any operations with a lower QoS that are added to the queue in the future will infer the higher QoS.
However, this does not mean that op.qualityOfService
property is modified by the OperationQueue
, because that would erase the QoS that you assigned to the operation. In other words, the value of the op.qualityOfService
might not represent the promoted QoS, only the one that you assigned (or .default
).
According to swift's implementation of Operation.swift
, the op.queuePriority
is the property that represents the actual priority in the queue, after all the complicated logic of QoS inference and promotion is applied. You can map it back to QoS, same way as it's done forwards in the code I've just referred
来源:https://stackoverflow.com/questions/66051129/confused-about-operation-and-operationqueue-qos-relationship