DispatchGroup.wait不等待

时间:2017-09-28 20:46:49

标签: ios swift xcode bluetooth-lowenergy

我有理解或使用Dispatchgroup的问题。我已经阅读了很多关于它们的内容,但是大多数示例/文档都非常模糊,或者与我想要做的事情不相似,但是每当我提到我的问题时,每个人都说"使用调度组!&# 34。

这是我想做的事情(注:序贯顺序很重要):

  • 发送蓝牙写入特性。
  • 设备接收值,并在响应中吐出内容
  • 读取蓝牙响应(通过读取特性)
  • 发送新的写入特征(不同的命令)
  • 设备接收新命令,吐出新数据响应

重复两次(总共3个命令,总共3个不同的响应)。

我的代码:

func tPodInitialSetUp()
    {
        print ("* * * * * BEGIN SET-UP * * * * *")
        let setupDispatchGroup = DispatchGroup()

        setupDispatchGroup.enter()
        self.writeValue(command: Data(CommandModeCmd)) //231: Put t-Pod in command mode, burst mode is OFF returns OK
        setupDispatchGroup.leave()

        setupDispatchGroup.wait()

        setupDispatchGroup.enter()
        deviceConnected?.readValue(for: deviceConnectedCh1n2Char!)
        print("Sent command 231: returned: \(receivedString1)")
        if receivedString1.lowercased() == "ok"
        {
            print("t-Pod burst mode is OFF")
        }
        setupDispatchGroup.leave()

        setupDispatchGroup.wait()

        setupDispatchGroup.enter()
        self.writeValue(command: Data(loadProbeCalCmd)) //202: load calibration constants of probe, returns ok or 0
        setupDispatchGroup.leave()

        setupDispatchGroup.wait()

        setupDispatchGroup.enter()
        deviceConnected?.readValue(for: deviceConnectedCh1n2Char!)
        print("Sent command 202: returned: \(receivedString1)")
        if receivedString1.lowercased() == "ok"
        {
            print("Probe Constants loaded")
        }
        if receivedString1 == "0"
        {
            print("No probe connected")
        }
        setupDispatchGroup.leave()

        setupDispatchGroup.wait()

        setupDispatchGroup.enter()
        self.writeValue(command: Data(probeSNCmd)) //205: load probe serial number
        setupDispatchGroup.leave()

        setupDispatchGroup.wait()

        setupDispatchGroup.enter()
        deviceConnected?.readValue(for: deviceConnectedCh1n2Char!)
        print("Sent command 205: returned: \(receivedString1)")
        if (receivedString1.count == 6)
        {
            print("received Probe SN: \(receivedString1)")
            probeSN = receivedString1
        }
        setupDispatchGroup.leave()

        setupDispatchGroup.notify(queue: .main)
        {
            tPodSN = String(describing: connectedDeviceName!.dropFirst(7))
            print ("* * * SET-UP COMPLETE * * *")
            self.writeValue(command: Data(resetCmd)) //200: resets t-Pod
            self.writeValue(command: Data(beaconOffCmd)) //211: turns beacon off (temperature output)
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)
        {
            self.dataDisplaySubView.isHidden = false
            print ("Adding observers!")

            NotificationCenter.default.addObserver(self, selector: #selector(self.updateIncomingData), name: NSNotification.Name(rawValue: DATA_PARSED), object: nil) //Run every time you receive data from BLE

            NotificationCenter.default.addObserver(self, selector: #selector(self.calculateTNU), name: NSNotification.Name(rawValue: TOGGLESWITCH_TOGGLED), object: nil) //Run in case the toggle switches change and data needs to be re-calculated

            NotificationCenter.default.addObserver(self, selector: #selector(self.parseReceivedData), name: NSNotification.Name(rawValue: DEVICE_FINISHED_SENT_DATA), object: nil) //Run every time you receive the notification that the whole data has been sent
        }
    }

这会调用蓝牙写命令,该命令具有以下代码并确认:

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor descriptor: CBDescriptor, error: Error?) {
        guard error == nil else {
            print("Error writing descriptor: " + (error?.localizedDescription)!)
            return
        }
        print("Descriptor Value sent")
    }

现在,这是我的输出:

* * * * * BEGIN SET-UP * * * * *
***** WRITING *****
Wrote: 1 bytes
***** WRITING *****
Wrote: 1 bytes
Sent command 231: returned: **T-Pod-9Ch**
***** WRITING *****
Wrote: 1 bytes
Sent command 202: returned: **T-Pod-9Ch**
***** WRITING *****
Wrote: 1 bytes
Sent command 205: returned: **T-Pod-9Ch**
* * * SET-UP COMPLETE * * *
***** WRITING *****
Wrote: 1 bytes
***** WRITING *****
Wrote: 1 bytes
Characteristic Value sent
Adding observers!
Characteristic Value sent
Characteristic Value sent
Characteristic Value sent
Characteristic Value sent
Clearing TNU Array

现在,您可以看到"发送的特征值"是蓝牙功能在发送值时给出的确认,但是这个输出是在它完成运行整个代码之后创建的,所以基本上它把命令放在某个管道中,忘了它们做了其他所有事情然后发送了命令,因此回应我读书都是胡说八道!正如您所看到的,所有收到的字符串都是 T-Pod-9Ch (这只是它的正常突发输出),我应该从命令得到的预期响应是OK,OK和6位数字(在那个命令) 请帮忙,我已经读了很多次关于调度组应该如何工作但是我不能让他们做我想做的事。

3 个答案:

答案 0 :(得分:1)

尝试!

离开()

必需的 DispatchQueue.global(qos:.background)
func dispatchGroup() -> String {

   var message = ""

   let group = DispatchGroup()

   group.enter()

   DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 5) {
        message = "Hiii Friends"
        group.leave()
   }

   group.wait()

   return message
}

答案 1 :(得分:0)

如果我的问题正确,您需要在发送新命令之前等待答案。

但是你的写作没有完成块,这就是为什么在你的情况下使用dispatchGroup是没有意义的。

以下代码是使用调度组的常见示例

func someMethod(completionHandler: @escaping ()-> Void) {


 //we need to get or set some data in separated queue
    DispatchQueue.global(qos: .background).async {

    let group = DispatchGroup()

    //let's say we have an array of urls and we need to load images and put them to an array
    for url in someUrlArray {
          group.enter()
          SomeLoaderClass.load(url) { image in
                //add received image

                //leave the group
               group.leave() 
           }
    }

    //now we need to wait until all images will be downloaded 
    group.wait()

    //then we can finish and call the completion in the main queue
    DispatchQueue.main.async {
         completionHandler()
    }
   }
}

在您的情况下,您可能有以下几种选择:

首先,如果您知道如果您发送一个命令并完全接收该命令的答案,您可以按顺序调用方法:

  1. 调用一种方法发送命令1

  2. 在收到命令1的答案后再调用另一种方法

  3. 调用另一种方法发送命令2

  4. 获得命令2的答案后还有一种方法 ...

  5. <磷>氮。完成设置

    就像我需要注册用户一样,我需要首先发送已定义的凭据,从服务器获取令牌,然后在其后运行。

    因此,您必须为每个命令添加一个额外的方法,然后根据顺序调用它们

    如果您无法识别哪个命令可以获得答案,并且您确定只发送一个命令并且只等待一个答案,那么您可以使用调度组方式如下:

    typealias Callback = ()->Void
    class SomeManagerClass {
           var callback: Callback?
    
           func initiateSetup(){
                  DispatchQueue.global(qos: .background).async { [weak self] in
                        let group = DispatchGroup()
                       //now we can send commands
                       group.enter()
                       self?.sendCommand(SomeDataForTheFirstCommand) {
                              //when the first answer will be received, it will init the callback, so you can leave the group now
                             group.leave()
                        }
                       //sending the second command
                        group.enter()
                       self?.sendCommand(SomeDataForTheSecondCommand) {
                              //waiting for the second answer will be received
                             group.leave()
                        }
    
                        //.... more commands sending same way
                        group.wait()
                        //now all commands was send and you got an answer for each
    
                        //finishing setup 
                             DispatchQueue.main.async{
                            self?.finishSetup()
                       }
                  }
           }
    
          func sendCommand(_ command: Data, callback: Callback?){
                 self.writeValue(command: command)
                 self.callback = callback 
          }
    
          func answerReceived(){
                 //this is just an example method that is called when you get an answer for any command
                //now we can callback 
                self.callback?()
          }
    
          func finishSetup(){
    
               //do something 
          }
    }
    

    如果您需要更多详细信息,请与我们联系

答案 2 :(得分:0)

使用调度组的示例

private func performTask1() -> String {
    print("Task1")
    var result: String?
    let background = DispatchQueue.global(qos: .background)

    let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()
    background.asyncAfter(deadline: .now() + 3) {
        result = "Task1 is performed"
         dispatchGroup.leave()
    }
   dispatchGroup.wait()
    return result!
}

尝试一下以了解DispactGroup的概念!