ios - 操作状态不是线程安全的 Swift

标签 ios swift multithreading nsoperation nsoperationqueue

我已经对Operation进行了子类化以支持异步操作。 名为 AsyncOperation 的新类并添加了名为 state 的新字段 这是一个枚举,用于帮助管理操作状态。

class AsyncOperation: Operation {
// DONE: State enum with keyPath property
enum State: String {
   case Ready, Executing, Finished

fileprivate var keyPath: String {
  return "is" + rawValue
  }
}

// DONE: state property
var state = State.Ready {
  willSet {
    willChangeValue(forKey: newValue.keyPath)
    willChangeValue(forKey: state.keyPath)
  }
  didSet {
  didChangeValue(forKey: oldValue.keyPath)
  didChangeValue(forKey: state.keyPath)
  }
 }
}




 extension AsyncOperation {
 // DONE: Operation Overrides
 override var isReady: Bool {
 return super.isReady && state == .Ready
 }

 override var isExecuting: Bool {
    return state == .Executing
 }

 override var isFinished: Bool {
   return state == .Finished
 }

 override var isAsynchronous: Bool {
  return true
 }

 override func start() {
  if isCancelled {
  state = .Finished
  return
 }
 main()
 state = .Executing
 }

override func cancel() {
   state = .Finished
 }

}

总的来说,这个子类运行得很好,我对此非常满意。 我遇到了一些奇怪的行为...... 在某些情况下,我会像这样向队列添加操作:

//this code happens in mainViewController

//op is an operation that belong to mainViewController and could dispatched to the queue from many places, its init called once in view did load. 
op = SomeAsyncOperation()


if(op.state == .Executing){
  queue.addOperatiom(op)
}

并且应用程序崩溃,因为操作已经以某种方式分派(dispatch)到队列,当我检查断点时,我创建的 state 属性是 Ready 并且 原始操作的 isExecuting 字段为 true。发生的情况是我的 state 属性和操作状态字段未同步。如果我检查不同实现中的 state 字段,它确实会进入 ExecutingFinished 我如何确保它们始终同步? p>

最佳答案

您应该使用 NSLock 来保护对 state 属性的读取和写入。

看一下 session 的示例代码 Advanced NSOperation摘自 WWDC 2015

重要的部分是:

/// Private storage for the `state` property that will be KVO observed.
private var _state = State.Initialized

/// A lock to guard reads and writes to the `_state` property
private let stateLock = NSLock()

private var state: State {
    get {
        return stateLock.withCriticalScope {
            _state
        }
    }

    set(newState) {
        /*
            It's important to note that the KVO notifications are NOT called from inside
            the lock. If they were, the app would deadlock, because in the middle of
            calling the `didChangeValueForKey()` method, the observers try to access
            properties like "isReady" or "isFinished". Since those methods also
            acquire the lock, then we'd be stuck waiting on our own lock. It's the
            classic definition of deadlock.
        */
        willChangeValueForKey("state")

        stateLock.withCriticalScope { Void -> Void in
            guard _state != .Finished else {
                return
            }

            assert(_state.canTransitionToState(newState), "Performing invalid state transition.")
            _state = newState
        }

        didChangeValueForKey("state")
    }
}

关于ios - 操作状态不是线程安全的 Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44850188/

相关文章:

iphone - 在方向锁定的情况下强制相机在风景中查看

ios - 此 iPhone 6s 运行的是 iOS 11.1.2 (15B202),此版本的 Xcode 可能不支持

c++ - QSemaphore 是否足以制作 QQueue 的线程安全类比?

multithreading - 线程安全是什么意思?

c++ - SLX 云是否允许自定义库?

ios - UIPresentationController 在巨大的延迟之后呈现

iphone - 使用 UIView 动画处理一系列动画的最佳方式

ios - 一起水平滚动 UICollectionView 的所有行

ios - 容器/XiB Swift 中的音频播放器

ios - popViewController 操作后的上边距 UITableViewController