Click here to Skip to main content
15,070,511 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Is there any way for an application to use the SerialPort object in .net 2.0 with FTDI USB-to-serial converter chips and survive gracefully when the device is disconnected? When an attempt to read from the device fails, my thread exits and tries to close the SerialPort object. The close fails with an Access Denied exception, but that's survivable. Unfortunately, the program later crashes with a "Safe Handle was Closed" ObjectDisposedException in some thread I don't control. A Google search found that the issue has been raised to Microsoft support, but they don't seem to think it's a problem. Is there a solution?
Posted

1 solution

We also use the FTDI driver and have the same issue. Unfortunately, there isn't much you can do about it. One strategy is to close the port whenever it's not in use. We also instruct our users to never remove the device during program operation unless instructed to do so.

You may benefit from using an object that detects USB connect/disconnect events. WMI provides functionality for this. I use it to make sure I don't try to connect to the FTDI device immediatley after is has been connected. You could tweak the code to fire events on disconnect, which will possibly allow a more graceful close. See the code example below for ideas:

using System;
using System.Collections.Generic;
using System.Text;
using System.Management;

namespace DiagnosticControllerComm
{
    class USBInsertRemoveDetect : IDisposable
    {
        public delegate void EventArrivedDelegate(object sender, EventArrivedEventArgs e);
        /// <summary>
        /// A disconnect or connect event was detected
        /// </summary>
        public event EventArrivedDelegate EventArrived;
        ManagementEventWatcher m_watcher = null;
        
        public void Start()
        {             
  
            WqlEventQuery query;               
                         
            // Bind to local machine 
              
            ManagementScope scope = new ManagementScope("root\\CIMV2"); 
              
            scope.Options.EnablePrivileges = true; //sets required privilege    
            query = new WqlEventQuery();                
            query.EventClassName = "__InstanceOperationEvent";                
            query.WithinInterval = new TimeSpan(0,0,0,0,500);
            query.Condition = @"TargetInstance ISA 'Win32_USBControllerDevice'"; 
            
            m_watcher = new ManagementEventWatcher(scope, query);                
            m_watcher.EventArrived += new EventArrivedEventHandler(UsbEventArrived);                
            m_watcher.Start();
            
  
        }
        
       
  
        public void UsbEventArrived(object sender, EventArrivedEventArgs e)            
        {
            if (EventArrived != null)
            {
                EventArrived(sender, e);
            }
          
            //Get the Event object and display it  
              
            //foreach(PropertyData pd in e.NewEvent.Properties)                
            //{  
              
            //    ManagementBaseObject mbo = null;  
                  
            //    if(( mbo = pd.Value as ManagementBaseObject) != null)
            //    {  
                  
            //        foreach(PropertyData prop in mbo.Properties)  
                      
            //        Console.WriteLine("{0} - {1}", prop.Name, prop.Value);  
                  
            //    }  
              
            //}  
  
        }

        #region IDisposable Members

        public void Dispose()
        {
            
            m_watcher.Dispose();
        }

        #endregion
    }
}
   
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900