I wonder how it is possible that this strcture throws an IOException on the Open line saying that this resource is already used but, at the same time, the IsOpen returns false. The close is executed in another thread.
I'm using .NET 6 and the nugget System.IO.Ports (6.0.0)
if(!serialPort.IsOpen)
{
serialPort.Open();
}
serialPort.Close(); -> This close is executed in another thread
if(!serialPort.IsOpen)
{
serialPort.Open(); //Throws IOException
}
The exception is:
Exception in open port: System.IO.IOException: Ya se está usando el recurso solicitado. : 'COM9'
at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
at System.IO.Ports.SerialPort.Open()
at ExtDeveloper.EmvConnector.AttemptReconnection(CancellationToken token)
This is the real code
//This task is responsible for calling every time the FSM. This task is in a separated class.
public async Task FSM_EMV(CancellationToken token)
{
bool stopFsm = false;
if (EmvSpecificConnector is not null)
{
try
{
while (!token.IsCancellationRequested && !stopFsm)
{
if (EmvSpecificConnector.GetInitEmvStatus())
{
stopFsm = await EmvSpecificConnector.SpecificFSM(token); //stopFSM is a flag that finalizes the task. But not used in our case
}
else
{
Console.WriteLine("Wait to reconnect");
await Task.Delay(10000, token);
Console.WriteLine("Attempting to reconnect");
EmvSpecificConnector.AttemptReconnection(token);
}
}
token.ThrowIfCancellationRequested();
}
catch (OperationCanceledException e)
{
Console.WriteLine("FSM CANCELED: " + e);
}
catch (Exception e)
{
Console.WriteLine("FSM unexpected exception: " + e);
}
}
}
--------------------------------------------------------------------------------------------------------------------------------------
//This functions are executed from a dll which is included and instanced during runtime in the previous class as a property
public void AttemptReconnection(CancellationToken token)
{
try
{
serialPort = new SerialPort(ConfigParam.SerialPort, int.Parse(ConfigParam.Baudrate), Parity.None, 8, StopBits.One)
{
Handshake = Handshake.None,
ReadTimeout = int.Parse(ConfigParam.ReadTimeout),
WriteTimeout = int.Parse(ConfigParam.WriteTimeout),
};
if(!serialPort.IsOpen)
{
serialPort.Open(); //This throws exception the second time it comes here. The first open works well, but after a close, it throws exception.
}
}
catch (Exception e)
{
Console.WriteLine("Exception in open port: " + e);
InitOk = false;
}
}
public async Task<bool> SpecificFSM(CancellationToken token)
{
try
{
switch (FsmVars.NextState)
{
case States.WAIT_ORDER: //Wait order from server
//In case we need to listen from different cancellation tokens, we need this list of tokens.
//https://learn.microsoft.com/en-us/dotnet/standard/threading/how-to-listen-for-multiple-cancellation-requests
using (CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(token, ServerTxToken.Token))
{
try
{
FsmVars.RqToEmv = await EmvMsgTools.WaitOrderFromServer(Ch_LinceToEmv, linkedCts); //Wait for a server order,
//but break if the serial device disconnects.
if(FsmVars.RqToEmv is not null)
{
FsmVars.NextState = States.READ_ORDERS;
}
else
{
if(token.IsCancellationRequested)
{
return true; //Stop FSM
}
else if(ServerTxToken.Token.IsCancellationRequested)
{
serialPort.Close(); //<- Here I close the serial port, if the
serialPort.Dispose();
serialPort = null;
return false; //Serial port has been closed and we need to reconnect. break the FSM but do not finish it.
}
}
}
catch (OperationCanceledException)
{
}
}
break;
case States.READ_ORDER:
break;
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}