如何在swift中终止异步执行调度队列?

时间:2018-02-23 21:11:32

标签: swift

我目前正在使用Particle的API进行事件流传输,我希望在某个未知的时间点终止事件订阅(我知道有一个定时终止接口)。

ParticleCloud.sharedInstance().subscribeToAllEvents(withPrefix: prefix, handler: { (eventOpt :ParticleEvent?, error : Error?) in
            if let _ = error {
                eprint (message: "Could not subscribe to events")
            } else {
                let serialQueue = DispatchQueue(label: "foo")
                serialQueue.async(execute: {
                    ...
                })
            }
        })

据我所知,swift中的DispatchQueue对象从池中获取空闲线程并运行我省略的函数(因为它与问题无关)。我想要一些方法稍后结束.async调用,因为它现在无限期地运行。

我查看了堆栈溢出,以便稍后暂停或恢复调度队列,例如:

ParticleCloud.sharedInstance().subscribeToAllEvents(withPrefix: prefix, handler: { (eventOpt :ParticleEvent?, error : Error?) in
            if let _ = error {
                eprint (message: "Could not subscribe to events")
            } else {
                let serialQueue = DispatchQueue(label: "foo")
                serialQueue.async(execute: {
                    ...
                })
                serialQueue.suspend() // EXC_BAD_INSTRUCTION
            }
        })

但结果是EXC_BAD_INSTRUCTION。诊断(无对象等)没有帮助。

不幸的是,我不知道如何给出这个问题的MVCE示例,因为它需要粒子硬件和particle.io上的注册帐户,所以我为此道歉。

subscribeToAllEvents的API位于:https://docs.particle.io/reference/ios/#events-sub-system

2 个答案:

答案 0 :(得分:1)

最简单的方法是使用OperationQueue代替DispatchQueue。将BlockOperation添加到队列并保留对操作的引用,然后您可以在操作上调用cancel以防止它执行(如果操作已经开始,但是,这不会停止它,所以如果这是一个问题,你可以让它的关闭定期检查它的isCancelled属性,如果找到true,则提前退出。

答案 1 :(得分:1)

引用subscribeToAllEventsWithPrefix:handler:的文档:

  

返回: eventListenerID函数将返回一个id类型对象作为eventListener注册唯一ID - 保留并将此对象传递给unsubscribe方法以删除此事件侦听器

它容易混淆,但要点是订阅函数返回一个对象。您应该将对象保留在实例属性中。当您准备取消订阅时,请将该对象传递给取消订阅功能。

所以:

// Instance property.
var subscription: Any?

subscription = ParticleCloud.sharedInstance().subscribeToAllEvents(withPrefix: prefix, handler: { ... })

// When it's time to unsubscribe...
if let subscription = subscription {
    ParticleCloud.sharedInstance().unsubscribeFromEvent(withID: subscription)
    self.subscription = nil
}