DispatchGroup.wait不等待 [英] DispatchGroup.wait not waiting

查看:85
本文介绍了DispatchGroup.wait不等待的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在理解或使用Dispatchgroup时遇到问题.我已经阅读了很多关于它们的文章,但是大多数示例/文档都非常模糊或与我想做的不一样,但是每次我提到我的问题时,每个人都会说使用分配组!".

I'm having an issue understanding or using Dispatchgroup. I've read a lot about them however most examples / documentation are very vague or doesn't resemble what I want to do, however every time I mention my problem everyone says "USE DISPATCH GROUPS!".

这就是我想要做的(注意:顺序订购是至关重要的):

Here's what I want to do(NOTE: SEQUENTIAL ORDER IS CRUCIAL):

  • 发送蓝牙写入特征.
  • 设备获得价值,并在响应中吐出一些东西
  • 读取蓝牙响应(通过读取特征)
  • 发送新的写特征(不同的命令)
  • 设备收到NEW命令,吐出NEW数据响应
  • Send Bluetooth Write characteristic.
  • device receives value, and spits something in response
  • Read Bluetooth response (via a read characteristic)
  • Send a new write characteristic (a different command)
  • device receives NEW command, spits NEW data response

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

Repeat twice (3 commands total, 3 different responses total).

我的代码:

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
        }
    }

这将调用具有以下代码和确认信息的蓝牙写入命令:

This calls the bluetooth write command which has the following code and confirmation:

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位数字(在该订单).
请帮忙,我已经阅读了很多次关于调度组应该如何工作的信息,但我只是不能让他们去做我想做的事情.

Now, as you can see "Characteristic Value Sent" is the confirmation the bluetooth function gives when it sends the value, however this output is created AFTER it finished running the entire code, so basically it put the commands in some pipeline, forgot about them did everything else and THEN sent the commands and therefore the response I'm reading are all nonsense! As you can see all received strings are T-Pod-9Ch (which is just its normal burst output), the expected responses I should get from the commands are OK, OK and a 6 digit number (in that order).
Please help, I've read so many times about how dispatch groups are supposed to work but I just can't get them to do what I want.

推荐答案

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

If I got your question right, you need to wait for an answer before sending new command.

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

But your writes doesn't have a completion block, that's why in your case using dispatchGroup makes no sense.

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

The code below is a common example to use dispatch groups

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()
    }
   }
}

根据您的情况,您可能有几种选择:

In your situation you may have several options:

首先,如果您知道如果发送一个命令并确切地收到该命令的答案,则可以按以下顺序调用方法:

First, if you know that if you send one command and receive an answer exactly for that command, you can call methods in order below:

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

  1. Call one method to Send command 1

在收到命令1的答案后,调用另一个方法

Call another method after an answer for command 1 will be received

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

Call yet another method to Send command 2

以及获得命令2答案后的另一种方法 ...

And one more method after getting an answer for command 2 ...

n.完成设置

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

Like if I need to register a user, I need to send defined credentials first, get token from the server, then run something after it.

因此,您将必须为每个命令添加一个附加方法,并根据顺序调用它们

So you will have to add an additional method for each command and you will call them according the order

如果您无法识别要为哪个命令获得答案,并且确定仅发送了一个命令并且仅等待了一个答案,则可以按以下说明的方式使用调度组:

If you can't recognize for which command you're going to get an answer and you sure that you've send only one command and waiting only one answer, then you can use dispatch group in the way described below:

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 
      }
}

如果您需要更多详细信息,请告诉我

Let me know if you need more details

这篇关于DispatchGroup.wait不等待的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆