Swift GCD 工作项分派队列正在取消

Swift GCD Work Item Dispatch queue cancelling

我有必须继续执行的操作,直到更改启动它们的开关。我曾尝试将 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()
    }
}

您需要在 class 的顶部声明 DispatchWorkItem 变量。在您的代码中,一旦编译器停止运行, work1 变量就变得不可访问。每次您更改开关时,都会初始化一个新的 DispatchWorkItem 变量。请通过以下示例正确使用具有 stop/resume 功能

的 DispatchWorkItem
    @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()
        }

    }

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