等待队列中的所有操作执行任务

问题描述:

之前完成我有一个操作的子类和操作队列maxConcurrentOperationCount = 1等待队列中的所有操作执行任务

这将执行我的操作按顺序,我将它们添加这是很好的,但现在我需要等到所有操作完成后再运行另一个进程。

我正在尝试使用通知组,但因为这是在for循环中运行,只要操作已被添加到通知组触发的队列中。如何等待所有操作在运行前离开队列另一个过程?

for (index, _) in self.packArray.enumerated() { 

    myGroup.enter() 
    let myArrayOperation = ArrayOperation(collection: self.outerCollectionView, id: self.packArray[index].id, count: index) 
    myArrayOperation.name = self.packArray[index].id 
    downloadQueue.addOperation(myArrayOperation) 
    myGroup.leave() 

} 

myGroup.notify(queue: .main) { 
// do stuff here 
} 
+1

将'myGroup.leave()'放在操作的完成块中。 – dan

+1

使用waitUntilAllOperationsAreFinished https://developer.apple.com/reference/foundation/operationqueue/1407971-waituntilalloperationsarefinishe – Paulw11

可以使用操作依赖来启动一些操作完成一系列其他操作后:

let operationQueue = OperationQueue() 

let completionOperation = BlockOperation { 
    // do something 
} 

for object in objects { 
    let operation = ... 
    completionOperation.addDependency(operation) 
    operationQueue.addOperation(operation) 
} 

OperationQueue.main.addOperation(completionOperation) 
+0

很干净。谢谢 – WanderingScouse

+0

嘿罗布,我已经完成了这一点,但我的'completionOperation'仍然被过早解雇。我的操作是异步网络操作,因此操作只在响应返回时才被视为“完成”。我读到我需要重写其他几个中的'isAsynchronous'属性以使其成为一个异步操作,但是我读到如果将操作添加到队列中,该属性将被忽略。所以我很困惑该怎么做。你能请进一步建议吗? – Pavan

+1

“我读过,我需要重写其他几个中的isAsynchronous属性,以使其成为异步操作”...是的,如果操作中的基础任务是异步的,那么是的,这是正确的。请参阅https://stackoverflow.com/a/32322851/1271826以获取'URLSession'的实现;请参阅https://stackoverflow.com/a/27022598/1271826获取Alamofire实现。 “但我读到,如果我将操作添加到队列中,该属性将被忽略。” ......这当然是不正确的。当为异步任务执行Operation子类时,isAsynchronous是很重要的。 – Rob

的合适的溶液是KVO

首先之前的循环添加观察者(假设queueOperationQueue实例)

queue.addObserver(self, forKeyPath:"operations", options:.new, context:nil) 

然后实现

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
    if object as? OperationQueue == queue && keyPath == "operations" { 
     if queue.operations.isEmpty { 
      // Do something here when your queue has completed 
      self.queue.removeObserver(self, forKeyPath:"operations") 
     } 
    } else { 
     super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) 
    } 
}