Azure / azure-iot-sdk-csharp

A C# SDK for connecting devices to Microsoft Azure IoT services
Other
470 stars 492 forks source link

[Technical Question] Why would device client become null #3471

Open Gamecock opened 3 months ago

Gamecock commented 3 months ago

We are using the IoTClient AMQP over Websockets, a very vanilla implementation following the reconnect sample, only using D2C and C2D messages. Occasionaly after a disconnect/Reconnect we start getting null references on the client we saved.

Simplified and redacted code Client Creation

            var transportType = TransportType.Amqp_WebSocket_Only;
            using (_deviceClient = DeviceClient.CreateFromConnectionString(_connectionString, transportType))
            {
                await DeviceClientSetup(deviceName);
            }

        public async Task DeviceClientSetup(string deviceName)
        {
            try
            {
                Log.Info("Creating device client");
                _deviceClient.SetConnectionStatusChangesHandler(ConnectionStatusChangeHandler);
                await _deviceClient.OpenAsync();
                Log.Info("Created device client");
                await _deviceClient.SetReceiveMessageHandlerAsync(ReceiveMessageAndCompleteAsync, _deviceClient);
                Log.Info($"FDIoTService connected to IoTHub as device: {deviceName}");
                await Task.Delay(-1);
            }
            catch (Exception ex)
            {
                Log.Warn($"IoTFDClient error: {ex.Message}.\nStack trace: {ex.StackTrace}");
                await Task.Delay(30000);
            }
        }```

Exception occurs in the await _deviceClient.SendEventAsync(message); line

        private async Task SendMessage(OurMessage OurMessage)
        {
            try
            {
                var OurMessageString = JsonConvert.SerializeObject(OurMessage);
                Microsoft.Azure.Devices.Client.Message message = new Microsoft.Azure.Devices.Client.Message(Encoding.UTF8.GetBytes(OurMessageString));

                await _deviceClient.SendEventAsync(message);
            }
            catch(Exception ex)
            {
                Log.Error($"Failed to send message: {ex.Message}. {ex.StackTrace}");
            }
        }

Log Example

|10003971 | 20240819 07:59:57:328 | ERR|   IoTService|  IoTServiceManager|ConnectionStatusChangeHandler|                   | device status=Disconnected_Retrying, reason=Communication_Error
|10003973 | 20240819 08:01:18:462 | INF|   IoTService|  IoTServiceManager|ConnectionStatusChangeHandler|                   | device status=Connected, reason=Connection_Ok
|10003977 | 20240819 08:25:12:327 | ERR|   IoTService|  IoTServiceManager|               SendMessage|                   |Failed to send message: Object reference not set to an instance of an object..    at (Object , Message )
   at IoTServiceManager.SendMessage(OurMessage OurMessage)

Any thoughts on where to look or how my deviceclient could be null, but connect reconnect continue to trigger the ConnectionStatusChanged Handler?

Is there a way to recover the deviceClient instance?