Search code examples
c#serial-portsafehandle

safe handle has been closed - numerous options to fix


I have a private function that creates a new serial port and opens it. From time to time, I get the "Safe handle has been closed" exception, that terminates the application. Now, I've been reading a few optional fixes and would like to know from your experience, what may be the real problem in my code. 1) Need to define the _serialPort variable outside of the scope of this private function. 2) The serial port's readTimeout property should not be infinite. 3) The using statement above disposes my portName variable.

SerialPort _serialPort;
string[] devices = 
ConfigurationManager.AppSettings["GasAnalyzerDeviceName"].Split(',');
string portName;
using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity"))
{
    portName = (from p in searcher.Get().Cast<ManagementBaseObject>()
                                let c = "" + p["Caption"]
                                where c != null
                                where devices.Any(d => c.Contains(d.Trim()))
                                from pn in SerialPort.GetPortNames()
                                where c.Contains(pn)
                                select pn).FirstOrDefault();

}
                if (portName == null)
                    portName = ConfigurationManager.AppSettings["GasAnalyzerPortName"];

                if (portName == null)
                    throw new Exception("Gas port not found");

                // Create a new SerialPort object with default settings.
                _serialPort = new SerialPort();

                // Set Serial port properties
                _serialPort.PortName = portName;
                _serialPort.BaudRate = 115200;
                _serialPort.DataBits = 8;
                _serialPort.Parity = Parity.None;
                _serialPort.StopBits = StopBits.One;
                _serialPort.Handshake = Handshake.None;
                _serialPort.ReadTimeout = Timeout.Infinite;//1200;
                _serialPort.WriteTimeout = 1200;

Thanks!


Solution

  • I think you can discard options 2) and 3).

    Number one is a possible candidate, but there is not enough code to be sure: If there are no other references to your SerialPort it becomes a candidate for garbage collection. Once it is garbage collected, any attempt to access it will result in an exception, tough I would expect a NullReferenceException.

    There can be another cause: if your serial port is emulated over e.g. a USB device, and that device gets removed while your application is running, the underlying connection will be disposed. When you try to use the SerialPort in your application after that has happened, you will get the 'safe handle has been closed' exception.