Object reference not set to an instance of an object System.IO.Ports

82 Views Asked by At

We have created a desktop app on .Net Framework using LattePanda to read sensor data from PCB using RS485 Communication Protocol. In c# part, we have used EasyModbus Library to read data. The app working well to some extent, but coming to some point it is throwing the following error:

Object reference not set to an instance of an object.   
at System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents(Object state)
at System.Threading.QueueUserWorkItemCallback.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

In the follwing you can see thec# code to create ModbusClient object and ReadInputRegisters() method. We couldn't find the cause of this termination.

private readonly SemaphoreSlim _lock = new (1, 1);

    private static ModbusClient CreateAndConnectClient(string comPort, int baudrate, byte unitIdentifier)
    {
        try
        {
            ModbusClient modbusClient = new(comPort)
            {
                UnitIdentifier = unitIdentifier,
                Baudrate = baudrate,
                Parity = Parity.None,
                StopBits = StopBits.One,
                ConnectionTimeout = 1000
            };
            modbusClient.Connect();
            return modbusClient;

        }
        catch (ModbusException ex) {
            Trace.WriteLine("ModbusException: " + ex.Message);
            throw; 
        }
        catch (Exception ex)
        {
            Trace.WriteLine("Unhandled Exception: " + ex.Message);
            throw;
        }
    }

    public async Task<int[]> ReadInputRegistersAsync(string comPort, int baudrate,  byte unitIdentifier, int startAddress, int quantity)
    {
        await _lock.WaitAsync();
        ModbusClient? modbusClient = null;
        try
        {
            // Attempt to create and connect the Modbus client
            modbusClient = CreateAndConnectClient(comPort, baudrate, unitIdentifier);


            // Check if the client was successfully created and connected
            // to avoid Exception --> "Object reference not set to an instance of an object" 
            if (modbusClient == null)
            {
                Trace.WriteLine("ModbusClient is null.");
                return new int[quantity];
            }

            var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
            return data;
            
        }
        catch (ModbusException ex)
        {
            Trace.WriteLine("ModbusException in ReadInputRegistersAsync: " + ex.Message);

            // Return a new empty integer array
            return new int[quantity];
        }

        catch (Exception ex)
        {
            Trace.WriteLine("Unhandled Exception in ReadInputRegistersAsync: " + ex.Message);
            return new int[quantity];
        }

        finally
        {
            if (modbusClient!=null && modbusClient.Connected)
            {
                modbusClient.Disconnect();
            }
            _lock.Release();
        }
    }

Then in the following class, we have called ReadInputRegistersAsync()

public List<RawInput> GetData(DateTime date)
        {
            var data = new List<RawInput>();
            var items = GetSensors();
            var groupeItems = items.GroupBy(i => i.SlaveID).ToList();

            foreach (var itemGroup in groupeItems)
            {
                var sensors = itemGroup.ToList();
                var sensor = sensors.OrderBy(i => i.InputCh).LastOrDefault();
                if (sensor == null) continue;
                var readTask = modbusManager.ReadInputRegistersAsync(
                    $"COM{sensor.SerPort}", 9600, (byte)itemGroup.Key, 0, sensor.InputCh);
                Trace.WriteLine("^^^^^^^^^^^^^^^^^^^ READ TASK SlaveID: " + (byte)itemGroup.Key);
                readTask.ContinueWith(task =>
                {
                    if (task.IsCompletedSuccessfully)
                    {
                        var list = task.Result.ToList();
                        data.AddRange(sensors.ConvertAll(s =>
                            new RawInput()
                            {
                                ItemId = s.Id,
                                RawValue = list[s.InputCh - 1]
                            }
                        ));
                    }
                    else
                    {
                        Trace.WriteLine("^^^^^^^^^^^^^^^^^^^ READ TASK IS NOT COMPLETED SUCCESSFULLY");
                        data.AddRange(sensors.ConvertAll(s => new RawInput()
                        {
                            ItemId = s.Id,
                            RawValue = 0
                        }));
                    }

                }).Wait();
            }

            return data;
        }
0

There are 0 best solutions below