【问题标题】:How can I Pause a NSOperation in a NSOperationQueue?如何在 NSOperationQueue 中暂停 NSOperation?
【发布时间】:2012-08-12 14:14:55
【问题描述】:

我需要暂停插入到 NSOperationQueue 中的正在运行的 NSOperation。目前我正在取消所有操作并重新启动它们。但这会导致在完成的​​过程方面出现某种重复。我尝试使用 NSOperationQueue 的 setSuspended 标志。但这并没有暂停操作。有什么办法吗?

【问题讨论】:

    标签: ios macos cocoa nsoperation nsoperationqueue


    【解决方案1】:

    看到这个:Link

    这里来自apple docs

    暂停和恢复队列 如果要暂时停止操作的执行,可以使用 setSuspended: 方法暂停相应的操作队列。

    暂停队列不会导致已经执行的操作在其任务中间暂停。它只是防止新操作被安排执行。您可能会暂停队列以响应用户暂停任何正在进行的工作的请求,因为预期用户最终可能希望恢复该工作。

    【讨论】:

    • 谢谢!我试图从您的链接中实施。我在 NSOperation 中添加了一个名为“isPaused”的新变量,每当我需要暂停操作时,我会将其值设置为 YES。在 NSOperation 内部,我会定期检查“isPaused”的值。每当我发现它为“是”时,我都会跳出循环。但我这里有严重的问题。我正在尝试从主线程设置“isPaused”的值。这可能会导致一些竞争条件。有没有办法摆脱竞争条件?有什么方法可以在同一个线程(而不是主线程)中调用方法(暂停和恢复)?
    • @Advaith:如果两个线程在读取或写入“isPaused”之前都锁定了一个互斥锁,那么您就不必担心竞争。
    【解决方案2】:

    我没有尝试过,但我可能会从这里开始:

    • isPaused 标志添加到您的NSOperation 子类
    • 实现操作数据的复制/移动方法
    • 如果暂停,setCancelled:(注意 -main 中的此更改)
    • 创建一个新操作,将状态从暂停操作转移到新操作
    • 如果您愿意,可以调整优先级以重新排列队列中的操作顺序
    • 将克隆添加到队列中
    • 如果在-main中,则从-main返回

    请注意,这只会暂停它。如果您真的想暂停并显式恢复,您可以在要恢复时手动“新操作”。

    现在,如果您正在观察或有特殊的补全,那么您将遇到一些其他问题。对于简单的情况,这种方法似乎可以正常工作。

    【讨论】:

      【解决方案3】:

      在 Swift 5 中,您可以使用 isSuspended 属性来暂停和恢复您的 OperationQueue,大家可以看例子了解更多:-

      let operationQueue = OperationQueue()
      
      let op1 = BlockOperation {
          print("done")
      }
      let op2 = BlockOperation {
          print("op2")
      }
      let op3 = BlockOperation {
          print("op3")
      }
      
      op1.addDependency(op2)
      operationQueue.addOperations([op1, op2, op3], waitUntilFinished: false)
      
      operationQueue.isSuspended = true
      print("operationQueue suspended")
      
      if operationQueue.isSuspended {
          operationQueue.isSuspended = false
          print("operationQueue restarted")
      }
      
      
      OutPut:- 
      op2
      op3
      operationQueue suspended
      operationQueue restarted
      done
      

      【讨论】: