快速 GCD 工作项调度队列取消



我有一些操作必须继续,直到启动它们的开关被更改。我尝试将 GCD 与工作项队列一起使用,相信异步操作将允许用户更改开关并因此停止操作。当代码运行时,它永远不会看到甚至触发开关更改。这是我的代码。知道我做错了什么吗?

@IBAction func trailerScanSwitchChange(_ sender: Any) {
let model = Model()     //Instantiate the Model
gScan = trailerScanSwitch.isOn
//Set up work iten to read and parse data
let work1 = DispatchWorkItem {
while (gScan && gConnected){
model.parseValues()
print ("parsing values")
if gScan == false || gConnected == false{
break
}
model.convertVoltsToLights()
self.updateLights()
print ("updating Lights")
if gScan == false || gConnected == false{
break
}
}
}
if trailerScanSwitch.isOn == true{
print ("Scanning")
//perform on the current thread
work1.perform()
//perpform on the global queue
DispatchQueue.global(qos: .background).async(execute: work1)  // concurrent actions
return
}
else {     //Stop reading and displaying
gScan = false
work1.cancel()
}
}

您需要在类的顶部声明 DispatchWorkItem 变量。在您的代码中,一旦编译器停止工作,work1 变量就会变得不可访问。每次更改交换机时,都会初始化一个新的调度工作项变量。请通过以下示例正确使用具有停止/恢复功能的调度工作项

@IBOutlet weak var button: UIButton!
@IBOutlet weak var label: UILabel!
var isStart = false
var work: DispatchWorkItem!
private func getCurrentTime() -> DispatchWorkItem {
work = DispatchWorkItem { [weak self] in
while true {
if (self?.work.isCancelled)!{break}
let date = Date()
let component = Calendar.current.dateComponents([.second], from: date)
DispatchQueue.main.async {
self?.label.text = "(component.second!)"
}
}
}
return work
}
@IBAction func btnPressed() {
isStart = !isStart
button.setTitle(isStart ? "Stop" : "Start", for: .normal)
let workItem = getCurrentTime()
let globalQueue = DispatchQueue.global(qos: .background)
if isStart {
globalQueue.async(execute: workItem)
} else {
workItem.cancel()
}
}

此示例将在标签中显示当前时间秒值。我使用而真实,只是为了展示一个例子。

最新更新