C#中MQTT订阅按钮点击后,如何接收命令行发布的消息?
解决C# MQTT订阅后接收消息的问题
你现在的核心问题是:订阅按钮的代码只是获取了client.MessageStream,但并没有监听这个流的消息事件或者异步遍历流中的消息,所以当命令行发布消息时,你的应用程序没有触发任何接收逻辑。下面给你两种可行的解决方案:
方案1:使用MessageReceived事件监听消息
这是传统的事件驱动方式,适配大多数场景:
首先,确保你的Mqtt客户端实例(client)是全局可访问的(比如声明为页面类的字段,而非局部变量),避免被垃圾回收导致无法接收消息。然后在订阅后绑定消息接收事件:
// 页面类字段,保存客户端实例 private IMqttClient _mqttClient; // 初始化客户端(建议放在页面Loaded事件中) private async void Page_Loaded(object sender, RoutedEventArgs e) { _mqttClient = new MqttFactory().CreateMqttClient(); var connectOptions = new MqttClientOptionsBuilder() .WithTcpServer("192.168.0.180") // 替换为你的Mosquitto Broker地址 .Build(); await _mqttClient.ConnectAsync(connectOptions); } private async void BtnSubscrbe_Click(object sender, RoutedEventArgs e) { // 订阅目标主题 await _mqttClient.SubscribeAsync("test1", MqttQualityOfService.ExactlyOnce); // 绑定消息接收事件(注意:多次点击订阅时,可先解绑再绑定避免重复触发) _mqttClient.MessageReceived += MqttClient_MessageReceived; } // 消息接收的处理逻辑 private void MqttClient_MessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e) { // 将字节数组消息转为字符串 var receivedContent = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); // 回到UI线程更新界面(比如显示到TextBlock) Dispatcher.Invoke(() => { txtReceivedMsg.Text = $"收到消息:{receivedContent}"; }); // 也可以在控制台输出调试 Console.WriteLine($"主题[{e.ApplicationMessage.Topic}]收到消息:{receivedContent}"); }
方案2:异步遍历MessageStream
如果你偏好C# 8.0+支持的异步流写法,可以这样实现:
private async void BtnSubscrbe_Click(object sender, RoutedEventArgs e) { await _mqttClient.SubscribeAsync("test1", MqttQualityOfService.ExactlyOnce); // 异步遍历消息流,该逻辑会持续运行直到客户端断开连接 await foreach (var msgWrapper in _mqttClient.MessageStream) { var receivedContent = Encoding.UTF8.GetString(msgWrapper.ApplicationMessage.Payload); // 必须通过Dispatcher更新UI Dispatcher.Invoke(() => { txtReceivedMsg.Text = $"收到消息:{receivedContent}"; }); Console.WriteLine($"主题[{msgWrapper.ApplicationMessage.Topic}]收到消息:{receivedContent}"); } }
关键注意事项
- 客户端实例必须全局持有,不能在按钮点击方法中创建局部实例,否则订阅后会被垃圾回收,无法持续接收消息。
- 由于MQTT消息接收线程是后台线程,更新UI时必须使用
Dispatcher.Invoke切换到主线程,否则会抛出跨线程操作异常。 - 若多次点击订阅按钮,方案1中要避免重复绑定
MessageReceived事件(可先执行_mqttClient.MessageReceived -= MqttClient_MessageReceived再绑定)。
内容的提问来源于stack exchange,提问作者rizwika
相关产品推荐
相关产品推荐

