franko_camron
franko_camron

Reputation: 1293

.NET Error Closing serial port BaseStream error is only available when the port is open

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

Answers (2)

Gianluca Ghettini
Gianluca Ghettini

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

Luca Del Tongo
Luca Del Tongo

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

Related Questions