Reputation: 1293
I'm using the .NET System.IO.Ports.SerialPort using the BaseStream as suggested in this post If you must use .NET System.IO.Ports.SerialPort
But when I try to close the port or the baseStream, an System.InvalidOperationException is raised saying "The BaseStream is only available when the port is open"
This is my code:
private void ActionStarted()
{
//ajusta el puerto
setupSerial();
serial.Open(); //conecta al plc
byte[] buffer = new byte[15];
Action kickoffRead = null;
if (serial.IsOpen)
{
kickoffRead = delegate()
{
serial.BaseStream.BeginRead(buffer, 0, buffer.Length,
delegate(IAsyncResult ar)
{
try
{
int actualLength = serial.BaseStream.EndRead(ar);
byte[] received = new byte[actualLength];
Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
raiseAppSerialDataEvent(received);
}
catch
{
//do something
}
kickoffRead();
}, null);
};
kickoffRead();
}
}
//<-- here is where the error occurs -->
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
serial.BaseStream.Flush();
serial.BaseStream.Close();
serial.Close();
}
I read somewhere that the serial port should be close on a different thread but I can't find that, so any thoughts??
Thanks!!
Upvotes: 3
Views: 4878
Reputation: 11628
As Luca correctly pointed out, you should check the status of the serial port before reading it.
You get the exception because your reading thread (the delegate) attempts to use a closed serial port.
Moreover, make use of the Dispose() method before closing the serial port. In general, if an object inherits IDisposable it is a good idea to dispose it when you no longer need it, especially if the object uses unmanaged resources like the serial port. Not disposing unmanaged resources will lead to memory leaks even in C# (the garbage collector doesn't collect unmanaged resources!)
Upvotes: 0
Reputation: 2702
I face the same problem as you described. Basically I solved with a proper disposal of the serial port resources and a check on port status before calling reading action. Here is the full code that open the port, read and close it.
public bool Open()
{
bool result = false;
try
{
this.serialPort.Open();
result = true;
startReading = StartAsyncSerialReading;
startReading();
}
catch (Exception)
{
this.Close();
result = false;
}
return result;
}
private void StartAsyncSerialReading()
{
byte[] buffer = new byte[bufferLength];
serialPort.BaseStream.BeginRead(buffer, 0, bufferLength, delegate(IAsyncResult ar)
{
try
{
if (serialPort.IsOpen)
{
actualReadLength = serialPort.BaseStream.EndRead(ar);
received = new byte[actualReadLength];
DoYourStuffWithDataBuffer();
}
}
catch (IOException exc)
{
//handleAppSerialError(exc);
}
if (serialPort.IsOpen)
startReading();
}, null);
}
protected Stream GetStream()
{
return this.serialPort.BaseStream;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
this.serialPort.Dispose();
this.disposed = true;
}
}
public void Close()
{
this.serialPort.Close();
this.Dispose();
}
Upvotes: 2