【问题标题】:Asynchronous Callback in NSOperation inside of NSOperationQueue is never calledNSOperationQueue 内部的 NSOperation 中的异步回调永远不会被调用
【发布时间】:2016-09-06 22:30:25
【问题描述】:

我需要将几个在一个NSOperationQueue 中进行网络调用的NSOperations 链接在一起,然后等待全部完成。

我将所有NSOperations 添加到我的NSOperationQueue,然后调用operationQueue.waitUntilAllOperationsAreFinished()。这可行,但它会无限期地等待,因为 NSOperations 中的回调将操作的状态设置为“已完成”,永远不会被调用。

我正在使用以下NSOperation 子类:

class ConcurrentOperation: NSOperation
{
    enum State: String
    {
        case Ready, Executing, Finished

        private var keyPath: String
        {
            return "is" + self.rawValue
        }
    }

    var state: State = State.Ready {
        willSet (newValue)
        {
            self.willChangeValueForKey(newValue.keyPath)
            self.willChangeValueForKey(self.state.keyPath)
        }

        didSet
        {
            self.didChangeValueForKey(oldValue.keyPath)
            self.didChangeValueForKey(self.state.keyPath)
        }
    }
}

extension ConcurrentOperation
{
    override var ready: Bool {
        return super.ready && self.state == .Ready
    }

    override var executing: Bool {
        return self.state == .Executing
    }

    override var finished: Bool {
        return self.state == .Finished
    }

    override var concurrent: Bool {
        return true
    }

    override var asynchronous: Bool {
        return true
    }
}

extension ConcurrentOperation
{
    override func start()
    {
        if self.cancelled
        {
            self.state = .Finished
            return
        }

        self.state = .Executing
        self.main()
    }

    override func cancel()
    {
        self.state = .Finished
    }
}

这是基于 Raywenderlich 教程和 https://gist.github.com/calebd/93fa347397cec5f88233

这应该做的是告诉 NSOperationQueue 只有当ConcurrentOperation 的子类中的main() 方法将状态设置为.Finished 时它才完成。 这也是通过操作实现的。

然而,如果我在这样的ConcurrentOperation 子类中构造以下main() 方法,NSOperationQueue 永远不会停止,因为 异步部分永远不会被调用

override func main()
{
    dispatch_async(dispatch_get_main_queue(), {
        sleep(1)
        self.state = .Finished  // never called!
    })
}

问题与我在应用中使用的 Firebase-Query 回调相同。

我试图覆盖concurrent: Bool 属性并返回true,但这也不能解决问题。

我怎样才能实现异步任务实际上是在我的ConcurrentOperation 子类'main() 方法中执行的?

谢谢!

【问题讨论】:

  • 您在主队列中呼叫waitUntilAllOperationsAreFinished 吗?如果是这样,那么您已经阻塞了主队列并且dispatch_async(dispatch_get_main_queue()... 代码没有机会执行
  • 我是。即使我在dispatch_async(_,_) 块中这样做,它确实阻塞了主队列。你真棒!谢谢!如果您定期回答我的问题,我会将其标记为正确。 @Paulw11

标签: ios swift asynchronous callback queue


【解决方案1】:

如果您在主队列上调用waitUntilAllOperationsAreFinished,那么您将阻塞主队列。一旦主队列被阻塞,dispatch_async(dispatch_get_main_queue(), 将无法执行,因为您已经创建了死锁;解除阻塞主队列需要执行的任务已经被调度到阻塞的主队列上,所以永远不会运行,也永远无法运行。

您需要在自己的队列中调度waitUntilAllOperationsAreFinished

【讨论】:

    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2013-11-23
    相关资源
    最近更新 更多