.NET客户端 - 在继续下一个请求之前等待MQTT响应

时间:2016-07-26 09:39:13

标签: c# .net mqtt

我在循环中有一个MQTT调用,并且在每次迭代中,它应该返回订阅者的响应,以便我可以使用我发布后转发的值。但问题是我不知道我该怎么做。

我希望你有一个想法,或者如果我没有正确实施它,你可以引导我完成这个。感谢。

这是我的代码:

// MyClientMgr
class MyClientMgr{

  public long CurrentOutput { get; set; }

  public void GetCurrentOutput(MyObjectParameters parameters, MqttClient client)
  {
      MyMessageObject msg = new MyMessageObject
      {
        Action = MyEnum.GetOutput,
        Data = JsonConvert.SerializeObject(parameters)
      }
      mq_GetCurrentOutput(msg, client);
  }

  private void mq_GetCurrentOutput(MyMessageObject msg, MqttClient client)
  {
      string msgStr = JsonConvert.SerializeObject(msg);
      client.Publish("getOutput", Encoding.UTF8.GetBytes(msgStr),   
MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
      client.MqttMsgPublishReceived += (sender, e) =>{
           MyObjectOutput output = JsonConvert.DeserializeObject<MyObjectOutput>(Encoding.UTF8.GetString(e.Message));
           CurrentOutput = output;
      };
  }  

}

// MyServerMgr
class MyServerMgr
{
   public void InitSubscriptions()
   {
      mq_GetOutput();
   }

   private void mq_GetOutput()
   {
       MqttClient clientSubscribe = new MqttClient(host);
       string clientId = Guid.NewGuid().ToString();
       clientSubscribe.Connect(clientId);
       clientSubscribe.Subscribe(new string[] { "getOutput" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });

       MqttClient clientPublish = new MqttClient(host);
       string clientIdPub = Guid.NewGuid().ToString();
       clientPublish.Connect(clientIdPub);
       clientSubscribe.MqttMsgPublishReceived += (sender, e) => {
            MyMessageObj msg = JsonConvert.DeserializeObject<MyMessageObj>(Encoding.UTF8.GetString(e.Message));

            var output = msg.Output;
            clientPublish.Publish("getOutput", Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(output)), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
       }
   }
}

// MyCallerClass
class MyCallerClass
{
   var host = "test.mqtt.org";
   var myServer = new MyServerMgr(host);
   var myClient = new MyClientMgr();

   myServer.InitSubscriptions();
   MqttClient client = new MqttClient(host);
   for(int i = 0; i < 10; i++)
   {
      long output = 0;

      MyObjectParameters parameters = {};
      myClient.GetCurrentOutput(parameters, client) // here I call the  method from my client manager 
      // to publish the getting of the output and assigned 
      // below for use,  but the problem is the value doesn't 
      // being passed to the output variable because it is not 
      // yet returned by the server.

      // Is there a way I could wait the process to 
      // get the response before assigning the output?

      output = myClient.CurrentOutput; // output here will always be null  
     // because the response is not yet forwarded by the server 

   }
}

我的调用者类中有一个循环来调用mqtt发布来获取输出,但是我不知道如何在分配之前获取输出,我想在转到下一个之前先等待响应。

我已经尝试过像这样做一个while循环:

while(output == 0)
{
   output = myClient.CurrentOutput;
}

是的,我可以在这里获得输出,但它会减慢这个过程。有时它会失败。

请帮帮我。感谢。

2 个答案:

答案 0 :(得分:0)

看起来您正在尝试通过异步协议(MQTT)进行同步通信。

我的意思是你要发送消息然后等待响应,这不是MQTT的工作原理,因为在协议级别没有回复消息的概念。

我对C#并不熟悉,所以我只是给出可能解决方案的抽象描述。

我的建议是使用发布线程,等待/脉冲(查看Monitor类)在每次发布后获得此块,并在收到响应时让消息处理程序调用脉冲。

如果响应没有等待识别原始请求,您还需要一个状态机变量来记录正在进行的请求。

你可能想看一下等待时间,以防另一方因某些原因没有回应。

答案 1 :(得分:0)

您可以使用具有WaitOne()和Set()方法的AutoResetEvent类。发布后使用WaitOne()将等待消息发布,并且在client_MqttMsgPublishReceived事件下使用Set()将在订阅者收到他订阅的消息时释放等待。