rossmann-engineering / EasyModbusTCP.NET

Modbus TCP, Modbus UDP and Modbus RTU client/server library for .NET implementations
922 stars 396 forks source link

The port is closed. at System.IO.Ports.SerialPort.DiscardInBuffer() #104

Closed akbarali2019 closed 6 months ago

akbarali2019 commented 10 months ago

The program is working well to some extent but frequently Disconnect() method is throwing this exception Error. I am using Modbus USB RS485 RTU for data transmission. Interestingly, it calls Disconnect() method after checking modbusClient is not null and Connected as it is mentioned below code. Besides, I have used lock.WaitAsync() mechanism to prevent calling the function by multiple threads. At least, I need to ignore the Exception or for the best case to find the root of the Exception. Here is the full text of the Exception error:

The port is closed. at System.IO.Ports.SerialPort.DiscardInBuffer() at EasyModbus.ModbusClient.DataReceivedHandler(Object sender, SerialDataReceivedEventArgs e) at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e) 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()

Here is the code I have implemented:

    private 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
            };
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus Connecting....");
            modbusClient.Connect();
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus CONNECTED");
            return modbusClient;

        }
        catch (ModbusException ex) {

            _seriaLogger.LogError("ModbusException in CreateAndConnectClient: {Message}", ex.Message);
            throw; 
        }
        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in CreateAndConnectClient: {Message}", ex.Message);
            throw;
        }
    }

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

            if (modbusClient == null)
            {
                _seriaLogger.LogInformation("ModbusClient is null. return new int[quantity]");
                return new int[quantity];
            }

            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters Reading Data....");
            var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters  return data: {data}", data);
            return data;

        }
        catch (ModbusException ex)
        {
            _seriaLogger.LogError("ModbusException in ReadInputRegistersAsync: {Message}", ex.Message);
            // Return a new empty integer array
            return new int[quantity];
        }

        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in ReadInputRegistersAsync: {Message}", ex.Message);
            return new int[quantity];
        }

        finally
        {
            if (modbusClient!=null && modbusClient.Connected)
            {
                _seriaLogger.LogInformation("modbusClient!=null && modbusClient.Connected....");
                try
                {
                    _seriaLogger.LogInformation("modbusClient.Disconnecting...");
                    modbusClient.Disconnect();
                    _seriaLogger.LogInformation("modbusClient.Disconnected");
                }
                catch (Exception ex)
                {
                    _seriaLogger.LogError("Unhandled Exception in serialport.Close() {Message}", ex.Message);
                }

            }
            _seriaLogger.LogInformation("_lock.Releasing...");
            _lock.Release();
            _seriaLogger.LogInformation("_lock.Released");
        }
    }
sushi1992 commented 6 months ago

The program is working well to some extent but frequently Disconnect() method is throwing this exception Error. I am using Modbus USB RS485 RTU for data transmission. Interestingly, it calls Disconnect() method after checking modbusClient is not null and Connected as it is mentioned below code. Besides, I have used lock.WaitAsync() mechanism to prevent calling the function by multiple threads. At least, I need to ignore the Exception or for the best case to find the root of the Exception. Here is the full text of the Exception error:

The port is closed. at System.IO.Ports.SerialPort.DiscardInBuffer() at EasyModbus.ModbusClient.DataReceivedHandler(Object sender, SerialDataReceivedEventArgs e) at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e) 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()

Here is the code I have implemented:

    private 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
            };
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus Connecting....");
            modbusClient.Connect();
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus CONNECTED");
            return modbusClient;

        }
        catch (ModbusException ex) {

            _seriaLogger.LogError("ModbusException in CreateAndConnectClient: {Message}", ex.Message);
            throw; 
        }
        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in CreateAndConnectClient: {Message}", ex.Message);
            throw;
        }
    }

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

            if (modbusClient == null)
            {
                _seriaLogger.LogInformation("ModbusClient is null. return new int[quantity]");
                return new int[quantity];
            }

            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters Reading Data....");
            var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters  return data: {data}", data);
            return data;

        }
        catch (ModbusException ex)
        {
            _seriaLogger.LogError("ModbusException in ReadInputRegistersAsync: {Message}", ex.Message);
            // Return a new empty integer array
            return new int[quantity];
        }

        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in ReadInputRegistersAsync: {Message}", ex.Message);
            return new int[quantity];
        }

        finally
        {
            if (modbusClient!=null && modbusClient.Connected)
            {
                _seriaLogger.LogInformation("modbusClient!=null && modbusClient.Connected....");
                try
                {
                    _seriaLogger.LogInformation("modbusClient.Disconnecting...");
                    modbusClient.Disconnect();
                    _seriaLogger.LogInformation("modbusClient.Disconnected");
                }
                catch (Exception ex)
                {
                    _seriaLogger.LogError("Unhandled Exception in serialport.Close() {Message}", ex.Message);
                }

            }
            _seriaLogger.LogInformation("_lock.Releasing...");
            _lock.Release();
            _seriaLogger.LogInformation("_lock.Released");
        }
    }

Hey! Did you ever find a solution to this?

akbarali2019 commented 6 months ago

The program is working well to some extent but frequently Disconnect() method is throwing this exception Error. I am using Modbus USB RS485 RTU for data transmission. Interestingly, it calls Disconnect() method after checking modbusClient is not null and Connected as it is mentioned below code. Besides, I have used lock.WaitAsync() mechanism to prevent calling the function by multiple threads. At least, I need to ignore the Exception or for the best case to find the root of the Exception. Here is the full text of the Exception error: The port is closed. at System.IO.Ports.SerialPort.DiscardInBuffer() at EasyModbus.ModbusClient.DataReceivedHandler(Object sender, SerialDataReceivedEventArgs e) at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e) 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() Here is the code I have implemented:

    private 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
            };
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus Connecting....");
            modbusClient.Connect();
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus CONNECTED");
            return modbusClient;

        }
        catch (ModbusException ex) {

            _seriaLogger.LogError("ModbusException in CreateAndConnectClient: {Message}", ex.Message);
            throw; 
        }
        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in CreateAndConnectClient: {Message}", ex.Message);
            throw;
        }
    }

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

            if (modbusClient == null)
            {
                _seriaLogger.LogInformation("ModbusClient is null. return new int[quantity]");
                return new int[quantity];
            }

            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters Reading Data....");
            var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters  return data: {data}", data);
            return data;

        }
        catch (ModbusException ex)
        {
            _seriaLogger.LogError("ModbusException in ReadInputRegistersAsync: {Message}", ex.Message);
            // Return a new empty integer array
            return new int[quantity];
        }

        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in ReadInputRegistersAsync: {Message}", ex.Message);
            return new int[quantity];
        }

        finally
        {
            if (modbusClient!=null && modbusClient.Connected)
            {
                _seriaLogger.LogInformation("modbusClient!=null && modbusClient.Connected....");
                try
                {
                    _seriaLogger.LogInformation("modbusClient.Disconnecting...");
                    modbusClient.Disconnect();
                    _seriaLogger.LogInformation("modbusClient.Disconnected");
                }
                catch (Exception ex)
                {
                    _seriaLogger.LogError("Unhandled Exception in serialport.Close() {Message}", ex.Message);
                }

            }
            _seriaLogger.LogInformation("_lock.Releasing...");
            _lock.Release();
            _seriaLogger.LogInformation("_lock.Released");
        }
    }

Hey! Did you ever find a solution to this?

Actually, I tried to catch the Exception but it is related with EasyModbus library itself. So I have implemented another library and now it is working without any errors or exceptions.

sushi1992 commented 6 months ago

The program is working well to some extent but frequently Disconnect() method is throwing this exception Error. I am using Modbus USB RS485 RTU for data transmission. Interestingly, it calls Disconnect() method after checking modbusClient is not null and Connected as it is mentioned below code. Besides, I have used lock.WaitAsync() mechanism to prevent calling the function by multiple threads. At least, I need to ignore the Exception or for the best case to find the root of the Exception. Here is the full text of the Exception error: The port is closed. at System.IO.Ports.SerialPort.DiscardInBuffer() at EasyModbus.ModbusClient.DataReceivedHandler(Object sender, SerialDataReceivedEventArgs e) at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e) 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() Here is the code I have implemented:

    private 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
            };
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus Connecting....");
            modbusClient.Connect();
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus CONNECTED");
            return modbusClient;

        }
        catch (ModbusException ex) {

            _seriaLogger.LogError("ModbusException in CreateAndConnectClient: {Message}", ex.Message);
            throw; 
        }
        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in CreateAndConnectClient: {Message}", ex.Message);
            throw;
        }
    }

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

            if (modbusClient == null)
            {
                _seriaLogger.LogInformation("ModbusClient is null. return new int[quantity]");
                return new int[quantity];
            }

            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters Reading Data....");
            var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters  return data: {data}", data);
            return data;

        }
        catch (ModbusException ex)
        {
            _seriaLogger.LogError("ModbusException in ReadInputRegistersAsync: {Message}", ex.Message);
            // Return a new empty integer array
            return new int[quantity];
        }

        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in ReadInputRegistersAsync: {Message}", ex.Message);
            return new int[quantity];
        }

        finally
        {
            if (modbusClient!=null && modbusClient.Connected)
            {
                _seriaLogger.LogInformation("modbusClient!=null && modbusClient.Connected....");
                try
                {
                    _seriaLogger.LogInformation("modbusClient.Disconnecting...");
                    modbusClient.Disconnect();
                    _seriaLogger.LogInformation("modbusClient.Disconnected");
                }
                catch (Exception ex)
                {
                    _seriaLogger.LogError("Unhandled Exception in serialport.Close() {Message}", ex.Message);
                }

            }
            _seriaLogger.LogInformation("_lock.Releasing...");
            _lock.Release();
            _seriaLogger.LogInformation("_lock.Released");
        }
    }

Hey! Did you ever find a solution to this?

Actually, I tried to catch the Exception but it is related with EasyModbus library itself. So I have implemented another library and now it is working without any errors or exceptions.

Oh nice! May I ask which library you used instead? Might have to switch to it if we can’t resolve this problem.

akbarali2019 commented 6 months ago

The program is working well to some extent but frequently Disconnect() method is throwing this exception Error. I am using Modbus USB RS485 RTU for data transmission. Interestingly, it calls Disconnect() method after checking modbusClient is not null and Connected as it is mentioned below code. Besides, I have used lock.WaitAsync() mechanism to prevent calling the function by multiple threads. At least, I need to ignore the Exception or for the best case to find the root of the Exception. Here is the full text of the Exception error: The port is closed. at System.IO.Ports.SerialPort.DiscardInBuffer() at EasyModbus.ModbusClient.DataReceivedHandler(Object sender, SerialDataReceivedEventArgs e) at System.IO.Ports.SerialPort.CatchReceivedEvents(Object src, SerialDataReceivedEventArgs e) 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() Here is the code I have implemented:

    private 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
            };
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus Connecting....");
            modbusClient.Connect();
            _seriaLogger.LogInformation("ModbusClient CreateAndConnectClient() Modbus CONNECTED");
            return modbusClient;

        }
        catch (ModbusException ex) {

            _seriaLogger.LogError("ModbusException in CreateAndConnectClient: {Message}", ex.Message);
            throw; 
        }
        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in CreateAndConnectClient: {Message}", ex.Message);
            throw;
        }
    }

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

            if (modbusClient == null)
            {
                _seriaLogger.LogInformation("ModbusClient is null. return new int[quantity]");
                return new int[quantity];
            }

            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters Reading Data....");
            var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
            _seriaLogger.LogInformation("modbusClient.ReadInputRegisters  return data: {data}", data);
            return data;

        }
        catch (ModbusException ex)
        {
            _seriaLogger.LogError("ModbusException in ReadInputRegistersAsync: {Message}", ex.Message);
            // Return a new empty integer array
            return new int[quantity];
        }

        catch (Exception ex)
        {
            _seriaLogger.LogError("Unhandled Exception in ReadInputRegistersAsync: {Message}", ex.Message);
            return new int[quantity];
        }

        finally
        {
            if (modbusClient!=null && modbusClient.Connected)
            {
                _seriaLogger.LogInformation("modbusClient!=null && modbusClient.Connected....");
                try
                {
                    _seriaLogger.LogInformation("modbusClient.Disconnecting...");
                    modbusClient.Disconnect();
                    _seriaLogger.LogInformation("modbusClient.Disconnected");
                }
                catch (Exception ex)
                {
                    _seriaLogger.LogError("Unhandled Exception in serialport.Close() {Message}", ex.Message);
                }

            }
            _seriaLogger.LogInformation("_lock.Releasing...");
            _lock.Release();
            _seriaLogger.LogInformation("_lock.Released");
        }
    }

Hey! Did you ever find a solution to this?

Actually, I tried to catch the Exception but it is related with EasyModbus library itself. So I have implemented another library and now it is working without any errors or exceptions.

Oh nice! May I ask which library you used instead? Might have to switch to it if we can’t resolve this problem.

Sure! We've used a FluentModbus library, it is a bit different from EasyMosbus library in terms of implementation. You may need to have a few changes. Here you can find info about implementation of FluentModbus using .NET C# https://apollo3zehn.github.io/FluentModbus/