如何确保OperationQueue中的操作一个接一个地完成
执行相互依赖的OperationQueue
,可以使用OperationQueue
来确保以正确的顺序执行它们。 但是,也可以保证操作一个接一个地完成?
让我们假设一个执行asynchronous的方法,需要一些时间来完成:
public func performOperation(_ number: Int, success: @escaping (Int) -> Void)->Void { DispatchQueue(label: "operations").async { print("Operation #\(number) starts") usleep(useconds_t(1000-number*200)) // Block thread for some time success(number) } }
操作和依赖关系创build如下:
let operationQueue = OperationQueue.main for operationNumber in 0..<4 { // Create operations as an example let operation = BlockOperation(block: { performOperation(operationNumber) { number in DispatchQueue.main.sync { print("Operation #\(number) finished") } } }) operation.name = "Operation #\(operationNumber)" if operationNumber > 0 { operation.addDependency(operationQueue.operations.last!) // Print dependencies print("\(operation.name!) should finish after \(operation.dependencies.first!.name!)") } operationQueue.addOperation(operation) }
有了以下输出:
Operation #1 should finish after Operation #0 Operation #2 should finish after Operation #1 Operation #3 should finish after Operation #2 Operation #0 starts Operation #1 starts Operation #2 starts Operation #3 starts Operation #0 finished Operation #3 finished Operation #2 finished Operation #1 finished
这显然是不正确的。 OperationQueue
似乎只能确保操作是以正确的顺序开始(而不是一个接一个地完成)。 虽然这可以使用DispatchSemaphore
来执行,但我想知道是否也可以使用OperationQueue
。
操作依赖关系正在完成,而不是开始操作,所以系统的行为就像那里logging的那样。 问题是DispatchQueue(label: "operations").async
– 你的performOperation
方法在你进入后立即退出, asynchronous调度print …; usleep …; success …
的顺序print …; usleep …; success …
print …; usleep …; success …
print …; usleep …; success …
,为每个执行操作调用创build一个新的调度队列。 然后,在Grand Central Dispatchpipe理的工作线程池的不同线程上执行print / sleep / successcallback序列。
我想这里你可能会感到困惑的是,认为反复声明DispatchQueue(label: "operations")
会得到相同的串行调度队列实例 – 事实并非如此,实际上你在每次调用时创build一个新的串行队列。
BlockOperation
说一下,在执行操作中没有任何理由创build或分配到一个串行调度队列,因为已经实现了BlockOperation
,使得该块在支持OperationQueue的GCD调度队列上同时执行( 并发也可以限制 ) 。 我会做你的情况是构造一个新的OperationQueue与OperationQueue()
(而不是使用OperationQueue.main
派遣工作在主队列),然后asynchronous调度您的成功callback到主队列。
这个稍微修改过的例子显示了操作的执行确实遵循了依赖关系(我没有实现上面的OperationQueue相关的build议,它可以说是在你提出的问题的旁边):
public func performOperation(_ number: Int, success: @escaping (Int) -> Void)->Void { print("Operation #\(number) starts") usleep(useconds_t(1000-(number*50))) // Block thread for some time success(number) } … let operationQueue = OperationQueue.main for operationNumber in 0..<8 { // Create operations as an example let operation = BlockOperation(block: { self.performOperation(operationNumber) { number in print("Operation #\(number) finished") } }) operation.name = "Operation #\(operationNumber)" if operationNumber > 0 { operation.addDependency(operationQueue.operations.last!) // Print dependencies print("\(operation.name!) should finish after \(operation.dependencies.first!.name!)") } operationQueue.addOperation(operation) }
这将输出…
Operation #1 should finish after Operation #0 Operation #2 should finish after Operation #1 Operation #3 should finish after Operation #2 Operation #4 should finish after Operation #3 Operation #5 should finish after Operation #4 Operation #6 should finish after Operation #5 Operation #7 should finish after Operation #6 Operation #0 starts Operation #0 finished Operation #1 starts Operation #1 finished Operation #2 starts Operation #2 finished Operation #3 starts Operation #3 finished Operation #4 starts Operation #4 finished Operation #5 starts Operation #5 finished Operation #6 starts Operation #6 finished Operation #7 starts Operation #7 finished
- 线程安全:NSOperationQueue +
- 为什么我应该为每个新线程或NSOperation创build一个NSManagedObjectContext,而不是在主线程上调用Core Data?
- 在iOS 7上使用Private Queue Deadlocks Parent的子级上下文执行块locking和等待
- 在当前队列上同步分派
- iOS GCD:任何全局队列和具有后台优先级(DISPATCH_QUEUE_PRIORITY_BACKGROUND)之间的区别?
- NSFetchedResultsController在合并“NSManagedObjectContextDidSaveNotification”后没有显示所有结果
- Swift 3 GCDlockingvariables和block_and_release错误
- 不同线程(主/专用队列)中的pipe理对象上下文是否可以处理相同的对象?
- 从asynchronousWeb服务响应更新托pipe对象的最佳方法?