none
SerialPort.Close throws IOException

    Question

  • Hi!

    I've read loads of pages regarding the System.IO.Ports.SerialPort object. I've included some of the better finding at the bottom of this message.

    I am using CF2 SP2, and VS 2005

    I am connecting my PPC 2003SE device to a GPS dongle using bluetooth. I have two problems I just can't get rid off.

    1.
    I don't get any information that the connection was broken. I.e. the gps dongle was shut down, out of range or similar. To remedy this I added a timer object to my gps-class that checks to see when the last transmitted data was received. If the time was to long ago it raises a timeout exception and tries to close the port. This leads me to question number 2.

    2.
    When closing the port, and the connection between the PDA and the GPS-dongle has been aborted, the port.Close() (or as in this call stack port.DiscardInBuffer()) call throws an IOException.

    System.IO.IOException was unhandled 
      Message="IOException" 
      StackTrace: 
        på System.IO.Ports.SerialStream.WinIOError() 
        på System.IO.Ports.SerialStream.WinIOError() 
        på System.IO.Ports.SerialStream.CheckResult() 
        på System.IO.Ports.SerialStream.DiscardInBuffer() 
        på System.IO.Ports.SerialPort.DiscardInBuffer() 
        på SIB.GPS.SIBGPS.CloseGPS() 
        på SIB.GPS.SIBGPS.ReceiveDataTimeOutCheck() 
        på System.Threading.Timer.ring() 
     


    Any ideas why this is happening?

    Thanks,

     Peter

    Resources:
    Serial Port Top 5 tips by Kim Hamilton
    http://www.innovatic.dk/knowledg/SerialCOM/SerialCOM.htm
    http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/10673e18-beba-4f0a-bb90-44e2aeeb74da/


    • Edited by phartlen Friday, March 27, 2009 9:42 AM Added resources
    Friday, March 27, 2009 9:39 AM

Answers

  • I runned into this issue several times too, specially in cases where an opened COM port disappears from the system.
    In that particular case, com port handle becomes invalid, and you have an IOException raised.

    For handling that case, I added IOException catch blocks whenever it can happen. In those blocks I try to close the COM port (which again can/will trigger an IOException), I then dispose the SerialPort object, and finally set it to null.

    By doing this (and by using CF2 SP2) I have never found myself again in a position where a com port becomes unusable because handles were not properly released. When the COM port is made available again on the system(in your case, by reconnecting the dongle),  it will be accessible like it was before all the IOException and its treatment.

    • Proposed as answer by Akhena Friday, March 27, 2009 1:13 PM
    • Marked as answer by phartlen Friday, March 27, 2009 1:17 PM
    Friday, March 27, 2009 10:08 AM

All replies

  • I runned into this issue several times too, specially in cases where an opened COM port disappears from the system.
    In that particular case, com port handle becomes invalid, and you have an IOException raised.

    For handling that case, I added IOException catch blocks whenever it can happen. In those blocks I try to close the COM port (which again can/will trigger an IOException), I then dispose the SerialPort object, and finally set it to null.

    By doing this (and by using CF2 SP2) I have never found myself again in a position where a com port becomes unusable because handles were not properly released. When the COM port is made available again on the system(in your case, by reconnecting the dongle),  it will be accessible like it was before all the IOException and its treatment.

    • Proposed as answer by Akhena Friday, March 27, 2009 1:13 PM
    • Marked as answer by phartlen Friday, March 27, 2009 1:17 PM
    Friday, March 27, 2009 10:08 AM
  • Hi and thanks for your reply.

    Catching an exception I don't know where it comes from isn't really what I want, but it does seem to solve issue number 2.

    Regarding issue 1. What is the PinChanged event used for? I recall reading someone saying the PinChanged event was fired when a connection was terminated abnormaly, could this be so?

    As it seems, the following PinChange events are fired when the connetion is terminated:

    CtsChanged
    DsrChanged
    CDChanged

    Thanks,

     Peter
    • Edited by phartlen Friday, March 27, 2009 10:33 AM
    Friday, March 27, 2009 10:26 AM
  • Yes it may sound strange having to catch an exception like this on every call to the SerialPort object, but I haven't found another way to correctly handle this particular case.

    The Pinchanged event can be fired on 5 cases : CD change, CTS change, DSR change, RI change, and Break. Those signals depend on the device you have connected to your com port. With a gps receiver, I don't think those signals will change (most of the time, gps receivers only use TX and RX lines).
    With other devices, CD or CTS can be used for knowing if there really is a device connected to the com port, thus with the PinChanged event you can detect when pda is connected/disconnected to the remote device (a modem for example).
    Friday, March 27, 2009 10:33 AM
  • Ok, but how do I know, for example if I get a CDChanged, that this indicates that a connection was made or a connection was terminated?
    Friday, March 27, 2009 10:38 AM
  • When you have a CDChanged event, you then check your SerialPort.CDHolding status for knowing if signal was raised or lowered. Raised will mean a connection has been physically made, lowered will mean the device was physically disconnected.

    This is only valid if the connected device does indeed raise it's CD signal when connected and running.
    Friday, March 27, 2009 10:45 AM
  • Ok, thanks.

    Well as I don't seem to get any PinChanged when I open the port I assume there is no CD signal raised. The big question is then if I can rely on this CD signal when the connection breaks...?!?

    The reason I want to know this is because right now I have a timer that checks last time data was retrieved, if the time diff between the check and last time data was retrieved is to great I signal a timeout exception to make sure the port is closed properly. But I rather not have this timer, if I could get a signal on a connection break any other way...

    BTW. You wouldn't have run into a similar issue with the port beeing "corrupted" when the device is shut down while a serial port was open?
    See this discussion: SerialPort object corrupted after power off

    Thanks,

     Peter
    Friday, March 27, 2009 11:01 AM
  • Well the best way to know is to test it by yourself with a small test app. You try disconnecting your dongle in different ways and check each time if you receive a CDChanged event (or other signal).

    Concerning the case when the device goes to sleep with a serialport being opened, at first I detected the wakeup event on the device, and automatically closed and reopened the serialport. But that caused a few seconds freeze on the pda.

    Since I use the IOException catch blocks method I explained earlier, I don't take any action at all on the serialport after a sleep/wakeup. With CF2 SP2 most of the time you don't need to do anything.
    And if SerialPort is in a corrupt state (it can happen, especially when we use USB2Serial converters), it will be automatically detected and handled in the IOException block.

    And anyway, I also have a timer that checks every 30 seconds if any data was received in these last 30 seconds. If not, I also close the serial port and reopen it.
    Friday, March 27, 2009 11:13 AM