使用C#测试MQTTnet 4.1连接EMQX Broker时程序异常退出求助
我在VS2019环境中使用C#开发,安装了NuGet包MQTTnet.4.1.4.563,参考相关示例代码尝试连接本地运行的EMQX Broker(桌面客户端为MQTTX),但无法建立稳定连接以实现主题的发布与订阅。我的Angular Web客户端可正常与该Broker收发消息,但编写的Program.cs代码中,程序执行到await Task.Delay(TimeSpan.FromSeconds(10));时异常退出,VS输出窗口显示最终信息为The program '[787944] mqtt-dotnet-sample1.exe' has exited with code 0 (0x0).
我的Program.cs代码
using System; using System.Threading.Tasks; using System.Threading; using MQTTnet.Client; using MQTTnet.Extensions.ManagedClient; using MQTTnet; using System.Text.Json; namespace mqtt_dotnet_sample1 { class Program { static void Main(string[] args) { Task task = ConnectAndSendMessage(); } public static async Task ConnectAndSendMessage() { IManagedMqttClient _mqttClient = new MqttFactory().CreateManagedMqttClient(); MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder() .WithClientId("MY_CLIENT_ID") // 与Angular 14的TypeScript客户端使用相同的连接标识 .WithWebSocketServer("broker.emqx.io"); ManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder() .WithAutoReconnectDelay(TimeSpan.FromSeconds(60)) .WithClientOptions(builder.Build()) .Build(); // 设置事件处理器 _mqttClient.ConnectedAsync += _mqttClient_ConnectedAsync; _mqttClient.DisconnectedAsync += _mqttClient_DisconnectedAsync; _mqttClient.ConnectingFailedAsync += _mqttClient_ConnectingFailedAsync; // 连接到Broker Console.WriteLine("Attempting to connect to broker..."); await _mqttClient.StartAsync(options); // 每秒向Broker发送一条新消息 while (true) { string json = JsonSerializer.Serialize(new { message = "Hi from MqttNet", sent = DateTime.UtcNow }); await _mqttClient.EnqueueAsync("bob-top", json); await Task.Delay(TimeSpan.FromSeconds(10)); // ** 程序在此处退出 ** } Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg) { Console.WriteLine("Connected"); return Task.CompletedTask; }; Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg) { Console.WriteLine("Disconnected"); return Task.CompletedTask; }; Task _mqttClient_ConnectingFailedAsync(ConnectingFailedEventArgs arg) { Console.WriteLine("Connection failed check network or broker!"); return Task.CompletedTask; } } } }
VS输出窗口信息
'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: DefaultDomain): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\mqtt-dotnet-sample1.exe'. Symbols loaded. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\MQTTnet.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\MQTTnet.Extensions.ManagedClient.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.Text.Json.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\netstandard\v4.0_2.0.0.0__cc7b13ffcd2ddd51\netstandard.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\Microsoft.Bcl.AsyncInterfaces.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.Memory.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.ValueTuple.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.Text.Encodings.Web.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.Runtime.CompilerServices.Unsafe.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.Threading.Tasks.Extensions.dll'. 'mqtt-dotnet-sample1.exe' (CLR v4.0.30319: mqtt-dotnet-sample1.exe): Loaded 'c:\bob\dev\mqtt-dotnet-sample1\mqtt-dotnet-sample1\bin\Debug\System.Buffers.dll'. The program '[787944] mqtt-dotnet-sample1.exe' has exited with code 0 (0x0).
问题修复建议
1. 主线程未等待异步任务完成
Main方法仅创建异步任务但未等待其执行,导致主线程直接退出,整个程序终止。修改Main方法为异步并等待任务:
static async Task Main(string[] args) { await ConnectAndSendMessage(); }
如果是.NET Framework环境不支持异步Main,可改为:
static void Main(string[] args) { ConnectAndSendMessage().GetAwaiter().GetResult(); }
2. 事件处理函数定义位置错误
三个事件处理函数定义在while(true)循环之后,永远不会被执行到,导致事件绑定的是未初始化的委托。需要将函数定义移至事件绑定之前:
public static async Task ConnectAndSendMessage() { IManagedMqttClient _mqttClient = new MqttFactory().CreateManagedMqttClient(); // 先定义事件处理函数 Task _mqttClient_ConnectedAsync(MqttClientConnectedEventArgs arg) { Console.WriteLine("Connected"); return Task.CompletedTask; }; Task _mqttClient_DisconnectedAsync(MqttClientDisconnectedEventArgs arg) { Console.WriteLine("Disconnected"); return Task.CompletedTask; }; Task _mqttClient_ConnectingFailedAsync(ConnectingFailedEventArgs arg) { Console.WriteLine("Connection failed check network or broker!"); return Task.CompletedTask; } // 再创建客户端选项并绑定事件 MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder() .WithClientId("MY_CLIENT_ID") .WithWebSocketServer("ws://localhost:8083"); // 改为本地EMQX的WebSocket地址 ManagedMqttClientOptions options = new ManagedMqttClientOptionsBuilder() .WithAutoReconnectDelay(TimeSpan.FromSeconds(60)) .WithClientOptions(builder.Build()) .Build(); _mqttClient.ConnectedAsync += _mqttClient_ConnectedAsync; _mqttClient.DisconnectedAsync += _mqttClient_DisconnectedAsync; _mqttClient.ConnectingFailedAsync += _mqttClient_ConnectingFailedAsync; // 后续连接与循环逻辑... }
3. Broker地址不匹配
代码中使用的是公共Brokerbroker.emqx.io,但你实际要连接本地EMQX,需改为本地WebSocket地址(默认端口8083):ws://localhost:8083,如果用TCP连接则改为.WithTcpServer("localhost", 1883)。
4. ClientID重复问题
如果Angular客户端与C#客户端使用相同的MY_CLIENT_ID,Broker会强制踢掉之前的连接,导致不稳定。建议给C#客户端设置唯一的ClientID,例如:
.WithClientId($"C#_Client_{Guid.NewGuid()}")
内容的提问来源于stack exchange,提问作者bob.mazzo

