NSOperationQueue中的NSOperation中的异步回调从未被调用 [英] Asynchronous Callback in NSOperation inside of NSOperationQueue is never called

查看:245
本文介绍了NSOperationQueue中的NSOperation中的异步回调从未被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要链接几个 NSOperation 在一个 NSOperationQueue 中执行网络调用,然后等待所有完成。



我将所有 NSOperation 添加到我的 NSOperationQueue 然后调用 operationQueue.waitUntilAllOperationsAreFinished()。这个工作,但是它无限期地等待,因为 NSOperations 中的回调将操作的状态设置为完成,从不调用。



我使用以下 NSOperation 子类:

  class ConcurrentOperation:NSOperation 
{
enum State:String
{
case准备好,执行完成

private var keyPath:String
{
returnis+ 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)
}
}
}

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

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

override var finished:Bool {
return true
}
$ b重写var finished:Bool {
return self.state == .Finished
} b
$ b override var asynchronous:Bool {
return true
}
}

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

self .state =。执行
self.main()
}

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

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



这应该做的是告诉NSOperationQueue,只有当 main() c $ c> ConcurrentOperation 将状态设置为 .Finished ,它完成。 这也是由操作满足。



,如果我构造以下 > main()方法在这样的 ConcurrentOperation 子类中, 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(),将无法执行,因为你已经创建了死锁;需要执行的任务,



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


I need to chain together several NSOperations that do network calls in one NSOperationQueue and then wait for all to be completed.

I'm adding all of the NSOperations to my NSOperationQueue and then call operationQueue.waitUntilAllOperationsAreFinished(). This works, but it waits indefinitely, as the callbacks in the NSOperations, that set the operation's state to 'finished', get never called.

I'm using the following NSOperation subclass:

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
    }
}

This is based on a Raywenderlich Tutorial and https://gist.github.com/calebd/93fa347397cec5f88233 .

What this should do is tell the NSOperationQueue that only when the main() method in a subclass of ConcurrentOperation sets the state to .Finished it is completed. And this is also fulfilled by the operation.

However, If I construct the following main() method in such a ConcurrentOperation subclass, the NSOperationQueue never stops as the asynchronous part is never called:

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

The problem is the same with a Firebase-Query Callback that I use in my app.

I tried to override the concurrent: Bool property and return true, but that doesn't fix it neither.

How can I accomplish that asynchronous tasks are actually executed in my ConcurrentOperation subclass' main() method?

Thank you!

解决方案

If you call waitUntilAllOperationsAreFinished on the main queue then you will block the main queue. Once the main queue is blocked the dispatch_async(dispatch_get_main_queue(), won't be able to execute as you have created a deadlock; The task that needs to execute to unblock the main queue has been dispatched on the blocked main queue, so it will never run and can never run.

You need to dispatch the waitUntilAllOperationsAreFinished on its own queue.

这篇关于NSOperationQueue中的NSOperation中的异步回调从未被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆