Home > Blockchain >  .NET Unable to reopen Serial Port after usb reconnection
.NET Unable to reopen Serial Port after usb reconnection

Time:12-04

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.

  • Related