Disconnecting and reconfiguration
Clean disconnection scenarios
Section titled “Clean disconnection scenarios”If you want to close the connection intentionally, you should call CloseConnectionAsync. This explicitly signals the internal engine that the disconnection is planned, preventing SyMqttBox from triggering its automatic reconnection loop.
Depending on your application design, you will generally fall into one of two implementation patterns:
Scenario 1: SyMqttBox as a Singleton (Recommended)
Section titled “Scenario 1: SyMqttBox as a Singleton (Recommended)”If the box runs for the entire duration of the application, open it at startup and explicitly close it when the application lifecycle shuts down:
var mqttBox = new SyMqttBox();await mqttBox.OpenConnectionAsync();
// ... use throughout the application lifecycle ...
// Before the application stops completely:var disconnectResult = await mqttBox.CloseConnectionAsync();Scenario 2: Short-Lived / Transient instances
Section titled “Scenario 2: Short-Lived / Transient instances”If you use the box for brief, transient operations, always leverage the ‘await using’ pattern.
Because SyMqttBox implements IAsyncDisposable, it will automatically trigger a safe, timed-out disconnection and dispose of internal resources when exiting the scope.
await using (var transientBox = new SyMqttBox()){ // ... initialize and register topology ... await transientBox.OpenConnectionAsync();
// ... perform quick operations ...} // The connection closes automatically and cleanly here via DisposeAsyncThe risks of abandoning instances without proper disposal
Section titled “The risks of abandoning instances without proper disposal”If a connected SyMqttBox instance drops out of scope without calling CloseConnectionAsync() or utilizing the await using syntax, your application relies entirely on the .NET Garbage Collector (GC) to clean up.
Since asynchronous network calls cannot be safely executed inside a standard GC finalizer thread, the clean MQTT disconnect handshake is completely bypassed, triggering severe side effects:
- Ghost Connections on the Broker: The broker will not realize your client has abandoned the link until the keep-alive ping timer expires. During this window, connection slots are wasted, and messages might be routed to a dead path.
- Socket and Memory Leaks: The internal MQTT client spawns background tasks for network polling. Abandoning the instance leaves these background tasks alive, anchoring the TCP socket and its associated memory buffers, preventing the GC from freeing them.
- Delayed Last Will and Testament (LWT): If you configured a Last Will message, the broker will eventually publish it, but only after the hard network timeout occurs. A clean disconnect avoids this delay entirely.
- Dropped QoS Handshakes: Abruptly dropping the instance cuts off active QoS 1 or QoS 2 handshakes (
PUBACK/PUBREC), leading to unacknowledged messages being lost or duplicated upon the next application startup.
Advanced lifecycle: Reconfiguration
Section titled “Advanced lifecycle: Reconfiguration”In a real-world production environment, you might need to change your connection parameters on the fly—such as switching to a backup broker IP, changing user credentials, or updating a TLS certificate—without restarting the entire application process.
Because SyMqttBox freezes its topology and client configuration while connected, you must follow a strict, coordinated sequence to reconfigure it safely:
- Close the active connection: Call
CloseConnectionAsync()to stop traffic and halt the automatic retry loop. - Re-initialize with new parameters: Call
Initialize()again, passing a brand-new instance ofSyMqttClientParameters. The internal engine will automatically detach old event handlers, safely dispose of the previous internal client, and build a new one. - Open the new connection: Call
OpenConnectionAsync()to resume operations.
Topology preservation
Section titled “Topology preservation”When you re-initialize the box, your registered channels and topic holders are completely preserved in memory. You do not need to register your topology again. The moment the new connection opens, the box automatically resubscribes all existing channels and topics to the brand-new broker target.
using SyMqtt;
// 1. Stop the current connection safelyawait mqttBox.CloseConnectionAsync();
// 2. Define your new network target profile (e.g., fallback server)// (Note: Unspecified properties like User, Password, protocol etc. will fall back to their class defaults)var backupParams = new SyMqttClientParameters{ TcpServer = "backup-broker.company.local", TcpPort = 1883, CleanSession = true};
// 3. Re-initialize the engine (wipes the old client, keeps your channels intact)mqttBox.Initialize(backupParams);
// 4. Reconnect to the new broker targetvar repairResult = await mqttBox.OpenConnectionAsync();
if (repairResult.Success){ Console.WriteLine("Reconfigured and reconnected to the backup broker successfully.");}By mastering this lifecycle loop, you can ensure your application remains highly resilient, stable, and flexible under any changing network conditions, completely free of resource leaks.