You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:01:10