ObjectDisposedException beim schließen SerialPort-in .Net 2.0

Habe ich eine C# - windows forms-Anwendung die Kommunikation mit einem USB-dongle über einen COM-port. Ich bin mit der SerialPort-Klasse .Net 2.0 für die Kommunikation und die serielle port-Objekt ist offen für die gesamte Lebensdauer der Anwendung. Die Anwendung sendet Befehle an das Gerät, und Sie können auch erhalten unerwünschte Daten aus dem Gerät.

Mein problem tritt auf, wenn das Formular geschlossen ist - ich (zufällig, leider) eine ObjectDisposedException beim Versuch, schließen Sie die COM-port. Hier ist der Windows-stack-trace:

System.ObjectDisposedException was unhandled


Message=Safe handle has been closed
  Source=System
  ObjectName=""
  StackTrace:
       at Microsoft.Win32.UnsafeNativeMethods.SetCommMask(SafeFileHandle hFile, Int32 dwEvtMask)
       at System.IO.Ports.SerialStream.Dispose(Boolean disposing)
       at System.IO.Ports.SerialStream.Finalize()
  InnerException: 

Ich gefunden habe, Beiträge von Menschen mit ähnlichen Problemen und haben versucht, die Abhilfe [hier][1]

[1]: http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html obwohl, dass ist für eine IOException aus, und wollte nicht aufhören, das problem.

Mein Close () - code ist wie folgt:

        public void Close()
    {
        try
        {
            Console.WriteLine("******ComPort.Close - baseStream.Close*******");
            baseStream.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("******ComPort.Close baseStream.Close raised exception: " + ex + "*******");
        }
        try
        {
            _onDataReceived = null;
            Console.WriteLine("******ComPort.Close - _serialPort.Close*******");
            _serialPort.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("******ComPort.Close - _serialPort.Close raised exception: " + ex + "*******");
        }            
    }

Meine Anmeldung zeigte, dass die Ausführung nie über Versuch, in der Nähe der SerialPort ist BaseStream (dies ist in der ersten try block), so experimentierte ich mit dem entfernen dieser Zeile, sondern die Ausnahme ist, noch geworfen, in regelmäßigen Abständen - die Protokollierung in der zweiten try block erschien dann die Ausnahme passiert ist. Weder catch-block fängt die Ausnahme.

Irgendwelche Ideen?

UPDATE - hinzufügen voll Klasse:

    namespace My.Utilities
{
    public interface ISerialPortObserver
    {
        void SerialPortWriteException();
    }

    internal class ComPort : ISerialPort
    {
        private readonly ISerialPortObserver _observer;
        readonly SerialPort _serialPort;

        private DataReceivedDelegate _onDataReceived;
        public event DataReceivedDelegate OnDataReceived
        {
            add { lock (_dataReceivedLocker) { _onDataReceived += value; } }
            remove { lock (_dataReceivedLocker) { _onDataReceived -= value; } }            
        }

        private readonly object _dataReceivedLocker = new object();
        private readonly object _locker = new object();

        internal ComPort()
        {         
            _serialPort = new SerialPort { ReadTimeout = 10, WriteTimeout = 100, DtrEnable = true };
            _serialPort.DataReceived += DataReceived;
        }

        internal ComPort(ISerialPortObserver observer) : this()
        {
            _observer = observer;         
        }

        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            DataReceivedDelegate temp = null;

            lock (_locker)
            {
                lock (_dataReceivedLocker)
                {
                    temp = _onDataReceived;
                }

                string dataReceived = string.Empty;
                var sp = (SerialPort) sender;

                try
                {
                    dataReceived = sp.ReadExisting();
                }
                catch (Exception ex)
                {
                    Logger.Log(TraceLevel.Error, "ComPort.DataReceived raised exception: " + ex);
                }

                if (null != temp && string.Empty != dataReceived)
                {
                    try
                    {
                        temp(dataReceived, TickProvider.GetTickCount());
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(TraceLevel.Error, "ComPort.DataReceived raised exception calling handler: " + ex);
                    }
                }
            }
        }

        public string Port
        {
            set
            {
                try
                {
                    _serialPort.PortName = value;
                }
                catch (Exception ex)
                {
                    Logger.Log(TraceLevel.Error, "ComPort.Port raised exception: " + ex);
                }
            }
        }

        private System.IO.Stream comPortStream = null;
        public bool Open()
        {
            SetupSerialPortWithWorkaround();
            try
            {
                _serialPort.Open();
                comPortStream = _serialPort.BaseStream;
                return true;
            }
            catch (Exception ex)
            {
                Logger.Log(TraceLevel.Warning, "ComPort.Open raised exception: " + ex);
                return false;
            }
        }

        public bool IsOpen
        {
            get
            {
                SetupSerialPortWithWorkaround();
                try
                {
                    return _serialPort.IsOpen;
                }
                catch(Exception ex)
                {
                    Logger.Log(TraceLevel.Error, "ComPort.IsOpen raised exception: " + ex);
                }

                return false;
            }
        }

        internal virtual void SetupSerialPortWithWorkaround()
        {
            try
            {
                //http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html
                //This class is meant to fix the problem in .Net that is causing the ObjectDisposedException.
                SerialPortFixer.Execute(_serialPort.PortName);
            }
            catch (Exception e)
            {
                Logger.Log(TraceLevel.Info, "Work around for .Net SerialPort object disposed exception failed with : " + e + " Will still attempt open port as normal");
            }
        }

        public void Close()
        {
            try
            {
                comPortStream.Close();
            }
            catch (Exception ex)
            {
                Logger.Log(TraceLevel.Error, "ComPortStream.Close raised exception: " + ex);
            }
            try
            {
                _onDataReceived = null;
                _serialPort.Close();
            }
            catch (Exception ex)
            {
                Logger.Log(TraceLevel.Error, "ComPort.Close raised exception: " + ex);
            }            
        }

        public void WriteData(string aData, DataReceivedDelegate handler)
        {
            try
            {
                OnDataReceived += handler;
                _serialPort.Write(aData + "\r\n");
            }
            catch (Exception ex)
            {
                Logger.Log(TraceLevel.Error, "ComPort.WriteData raised exception: " + ex);                

                if (null != _observer)
                {
                    _observer.SerialPortWriteException();
                }
            }
        }
    }    
}
  • Sie scheinen zu sein 'undicht' (nicht zu schließen oder zu entsorgen) Instanzen der SerialStream Klasse (seit SerialStream.Finalize ist aufgerufen, in Ihrem stack-trace), würde ich vorschlagen, dass dies ein problem, jedoch, um zu bestimmen, welche Beziehung dies trägt zu Ihrem aktuellen problem wir mehr Informationen benötigen.
  • Danke für die Antwort. Die Informationen helfen, zu lokalisieren des Problems?
  • Die gesamte Klasse, die enthält die Close oben genannte Methode helfen.
  • Dieser bug ist der pure Krebs und MS immer noch nicht das Problem behoben, jetzt im Jahr 2017
InformationsquelleAutor barry | 2012-01-19
Schreibe einen Kommentar