Swift-正在检查弱变量是否为零线程安全?
我有一个长时间运行的进程,我希望能够中断它Swift-正在检查弱变量是否为零线程安全?,swift,queue,thread-safety,weak-references,abort,Swift,Queue,Thread Safety,Weak References,Abort,我有一个长时间运行的进程,我希望能够中断它 func longProcess (shouldAbort: @escaping ()->Bool) { // Runs a long loop and periodically checks shouldAbort(), // returning early if shouldAbort() returns true } 下面是我使用它的班级: class Example { private var abortF
func longProcess (shouldAbort: @escaping ()->Bool) {
// Runs a long loop and periodically checks shouldAbort(),
// returning early if shouldAbort() returns true
}
下面是我使用它的班级:
class Example {
private var abortFlag: NSObject? = .init()
private var dispatchQueue: DispatchQueue = .init(label: "Example")
func startProcess () {
let shouldAbort: ()->Bool = { [weak abortFlag] in
return abortFlag == nil
}
dispatchQueue.async {
longProcess(shouldAbort: shouldAbort)
}
}
func abortProcess () {
self.abortFlag = nil
}
}
shoulldabort
闭包捕获对abortFlag
的weak
引用,并检查该引用是否指向nil
或NSObject
。由于引用是弱的
,如果原始的NSObject
被解除分配,那么闭包捕获的引用将突然变成nil
,闭包将开始返回true
。关闭将在longProcess
函数期间重复调用,该函数发生在私有dispatchQueue
上。Example
类上的abortProcess
方法将从其他队列外部调用。如果有人调用abortProcess()
,从而解除分配abortFlag
,而longProcess
正试图执行检查以查看abortFlag
是否已解除分配,该怎么办?检查myWeakReference==nil
是否为线程安全操作?您可以将已调度的任务创建为DispatchWorkItem
,它已经具有线程安全属性。然后,您可以将该DispatchWorkItem
分派到队列,并让它定期检查其isCancelled
。然后,您就可以在您想要停止它的时候将其调度为该点
或者,在尝试将某些工作包装到对象中时,我们通常使用
操作
,它将任务很好地封装在自己的类中:
class SomeLongOperation: Operation {
override func main() {
// Runs a long loop and periodically checks `isCancelled`
while !isCancelled {
Thread.sleep(forTimeInterval: 0.1)
print("tick")
}
}
}
要创建队列并将操作添加到该队列,请执行以下操作:
let queue = OperationQueue()
let operation = SomeLongOperation()
queue.addOperation(operation)
以及取消该项操作:
operation.cancel()
或
总之,无论您使用
操作
(坦率地说,这是将某个任务包装到自己的对象中的“转到”解决方案),还是使用DispatchWorkItem
滚动自己的解决方案,想法都是一样的,即您不需要拥有自己的状态属性来检测任务的取消。调度队列和操作队列都有很好的机制来简化这个过程。我看到这个bug()表明弱引用读取不是线程安全的,但它已经被修复,这表明(运行时没有任何bug),弱引用读取是线程安全的
同样有趣的是:首先为什么要使用这个虚拟的
NSObject
实例?看来这玩意儿也一样管用。忽略我的答案。事实上这是正确的(也很有趣),但罗布的建议更好。我同意Rob的建议是可行的,这就是为什么我投了更高的票,但我的问题只是部分出于需要,另一部分是好奇心。你直接回答了我的问题,所以你的答案是正确的。我很高兴读过Rob的答案,也很高兴这篇文章的一部分是供其他人阅读的
queue.cancelAllOperations()