参考https://developer.apple.com/reference/foundation/operation,我将Playground设置为 -
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.addOperation(op2)
控制台日志是 -
op1 working....
op2 working....
op1 finished
op2 finished
我们不应该期望输出是依赖的结果吗? -
op1 working....
op1 finished
op2 working....
op2 finished
使用 - opsQue.addOperations([op1, op2], waitUntilFinished: true)
op1 working....
op2 working....
op1 finished
op2 finished
答案 0 :(得分:3)
事实上,我无法确定为什么你的代码不能正常工作的原因是什么,但我想出了3个解决方法来实现你想要的东西:
如果您希望输出始终:
op1 working....
op1 finished
op2 working....
op2 finished
然后:
1 - 您可能希望将第二个操作添加到第一个操作的完成块中的队列中,如下所示:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let opsQue = OperationQueue()
let op1 = myOperation1()
op1.completionBlock = {
print("op1 finished")
opsQue.addOperation(op2)
}
let op2 = myOperation2()
op2.completionBlock = {
print("op2 finished")
}
opsQue.addOperation(op1)
2 - 将maxConcurrentOperationCount操作队列设置为1,如下所示:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
// setting maxConcurrentOperationCount to 1
opsQue.maxConcurrentOperationCount = 1
opsQue.addOperation(op1)
opsQue.addOperation(op2)
3 - 在将第一个操作添加到队列后调用waitUntilAllOperationsAreFinished(),如下所示:
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.waitUntilAllOperationsAreFinished()
opsQue.addOperation(op2)
不过,对于非复杂的任务,我更喜欢使用GCD。
希望这会有所帮助。
答案 1 :(得分:1)
根据完成模块(重点是我的)的文档,
不能保证用于完成块的确切执行上下文,但通常是辅助线程。因此,您不应使用此块来执行需要非常特定的执行上下文的任何工作。 https://developer.apple.com/documentation/foundation/operation/1408085-completionblock
因此,从更现实的意义上来说,当您想确切地知道某个操作何时完成时,您会执行以下操作:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
//Do things
print("op1 finished")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
//Do things
print("op2 finished")
}
}
答案 2 :(得分:1)
在依赖操作开始后调用完成块,但这并不意味着第一个操作没有结束。
如@Xoronis的答案中所述:
不能保证您的完成块的确切执行上下文,但通常是辅助线程。因此,您不应使用此块来执行需要非常特定的执行上下文的任何工作。
https://developer.apple.com/documentation/foundation/operation/1408085-completionblock
看看这个例子:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
for i in 1...10 {
print("\(i)")
}
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 completed")
}
op2.completionBlock = {
print("op2 completed")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperations([op1, op2], waitUntilFinished: true)
将导致
op1 working....
1
2
3
4
5
6
7
8
9
10
op2 working....
op1 completed
op2 completed
第一个操作确实在开始依赖之前结束,但是在依赖已经开始之后调用完成块。
答案 3 :(得分:1)
您需要将操作队列的maxConcurrentOperationCount设置为1,这样才能正常工作。
let operationQueue = OperationQueue()
operationqueue?.maxConcurrentOperationCount = 1
let operation1 = Operation()
let operation2 = Operation()
operation1.completionBlock = {
print("operation1 finished")
}
operation2.completionBlock = {
print("operation2 finished")
}
operation2.addDependency(operation1)
operationQueue.addOperation(operation1)
operationQueue.addOperation(operation2)
答案 4 :(得分:0)
通过指定依赖关系,可以保证op2
在op1
完成后进行调度,但不一定op2
在op1
的完成处理程序完成后进行调度
答案 5 :(得分:0)
初始化operationQueue暂停将为您提供所需内容。
let queue = OperationQueue()
let downloadOp = Operation()
let resizeOp = Operation()
downloadOp.dependency(resizeOp)
queue.isSuspended = true
queue.addOperation(downloadOp)
queue.addOperation(resizeOp)
queue.isSuspended = false
答案 6 :(得分:0)
我测试过使用isSuspended。每次操作完成后,即可操作主队列。
class OperationChain: Operation {
var mainQ: OperationQueue?
var text: String?
init(with name: String, by mainqueue:OperationQueue){
self.text = name
self.mainQ = mainqueue
}
override func main() {
self.mainQ!.isSuspended = true
print(text!)
sleep(5)
self.mainQ!.isSuspended = false
}
}
let oq = OperationQueue()
oq.maxConcurrentOperationCount = 1
let q1 = OperationChain(with: "Operation.main.q1", by: oq)
print("q1")
q1.completionBlock = {
//sleep(5)
q1.mainQ!.isSuspended = true
var i = 0
repeat {
i = i + 1
} while i < 100
print("q1.completionBlock")
q1.mainQ!.isSuspended = false
}
oq.addOperations([q1], waitUntilFinished: true)
答案 7 :(得分:0)
您可以使用适配器来确保执行顺序:
op1 working....
op1 finished
op2 working....
op2 finished
这是修改后的代码:
import Foundation
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
let adapter = BlockOperation(block: {})
adapter.addDependency(op1)
op2.addDependency(adapter)
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.addOperation(op2)
opsQue.addOperation(adapter)