I am trying to reopen a serial port after a device is unpluged and pluged. I have designed this little code to test. However, it throws IOException when repluguing the device and opening the port.
Console.WriteLine("Hello, World!");
SerialPort sp = new SerialPort("COM6",115200, Parity.None, 8, StopBits.One);
sp.Open();
Console.WriteLine("OPEN");
await Task.Delay(5000); //Here i disconnect the usb
sp.Close();
Console.WriteLine("CLOSE");
await Task.Delay(5000); //Here i reconnect the usb
sp.Open(); //Here it throws IOException, resource already in use
Console.WriteLine("OPEN");
I have done the same test in python and happens exactly the same
import serial as s
import time
ser = s.Serial('COM6',115200,parity=s.PARITY_NONE,\
stopbits=s.STOPBITS_ONE,\
bytesize=s.EIGHTBITS)
#ser.open()
print('Open')
time.sleep(5) #here I unplug the usb
ser.close()
print('close')
time.sleep(5) #here I plug the usb
ser.open() #here throws exception
print('open')
CodePudding user response:
The official MS serial port library has a bug in the close in which it does not really close the serial port as reported in https://github.com/jcurl/RJCP.DLL.SerialPortStream#21-issues-with-ms-serial-port which is an alternative library for serial port operations.
This library is installed through a NuGet package and creates a SerialPortStream object which inherits from Stream so it can be used as the official SerialPort.BaseStream from the official MS library.
A little example is the following one using tasks and asyncrhonous operations, but it also can be used with event handlers.
SerialPortStream sps = new SerialPortStream("COM6", 115200, 8, Parity.None, StopBits.One);
byte[] bytes_buff = new byte[300];
sps.Open();
Task.Run(async () =>
{
while (true)
{
int n_bytes = await sps.ReadAsync(bytes_buff.AsMemory(0, 300)).ConfigureAwait(false);
byte[] not_empty_bytes = bytes_buff[0..n_bytes];
Console.WriteLine("\nFrame: " BitConverter.ToString(not_empty_bytes) "\n");
}
});
await sps.WriteAsync(new byte[] { .... });
This example is a simple snippet but the serial port should be closed before exiting the program as well as the task used to read async with a cancellation token.