Microsoft Developer Network > Página principal de foros > Visual C# General > UnauthorizedAccessException on Serial Port after pulling the plug
Formular una preguntaFormular una pregunta
 

RespondidaUnauthorizedAccessException on Serial Port after pulling the plug

  • jueves, 05 de noviembre de 2009 18:52xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I have an application that has a serial to USB connector. When I connect to a port and pulls the plug from the USB and then reconnect the application itself works fine but when I close the application, I get UnauthorizedAccessException and I cannot figure out where it is thrown. I tried to run it in debugger but still no lead on where it is. I even tried to do

    try
    
    {
        Application.Run(new
     MyApplication());
    }
    catch
     (UnauthorizedAccessException e)
    {
        //Do something here
    
    }
    
    and still, this exception was not caught anywhere.

    What I want to achieve is to be able to handle the case when the application is connected to a port and then the plug the pulled or reconnected, the application should be able to handle it. Right now it crashes with that exception. I wonder if there is anyway to recover a lost COM port.

    Thanks

Respuestas

Todas las respuestas

  • jueves, 05 de noviembre de 2009 20:01Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    No doubt there is, but first things first.  Why the exception?

    Is your port being accessed through threads?
    That could cause the behavior you describe. 
    A thread exception being thrown when it tries to reference a disposed, unmanaged resource like a disconnected port.

    And it seems your threads can keep running even after the application has closed.  Gotta clean that up if that is the case.

    Mark the best replies as answers. "Fooling computers since 1971."
  • jueves, 05 de noviembre de 2009 20:11kevinwebster83 Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     

    I think the exception is thrown as the BaseStream of the SerialPort is being finalized when the plug is pulled. I've managed to overcome this error by adding a GC.SuppressFinalize call after calling SerialPort.Open, and then calling GC.ReregisterForFinalize (i think) method before i call SerialPort.Close. When doing this, i've never seen the exception occur again.

    Hope this helps

    Kev

  • jueves, 05 de noviembre de 2009 20:15kevinwebster83 Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    ... or maybe i've got that wrong, it may be that you call GC.SuppressFinalize before Open and GC.ReRegisterForFinalize after Close.

    As an extra comment, so far i've never been able to trap the UnauthorizedAccessException that is throw

    Kev
  • jueves, 05 de noviembre de 2009 20:34Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     

    There are just a couple of methods that can throw that exact esception.

    SerialPort.Open();
    SerialPort.Close();

    Those are two of the most prominent ones. 
    Most of the class members throw InvalidOperationExceptions.

    I would the actual hardware interaction is being done under a different thread.
    That might explain why some of those exceptions are so hard to catch.


    Mark the best replies as answers. "Fooling computers since 1971."
  • viernes, 06 de noviembre de 2009 17:29xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Tiene código
    The actual hardware interaction is done on the main thread. The problem is that when the main form is closed, I think, the system tries to release all the resources, including the comPort. But if the comPort was connected and then the line was physically unplugged, then the port is no longer there, thus this exception.

    I wrote a very simple program to test it out, and it was still giving me this error without any indication of where it was thrown.

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private SerialPort comPort = new SerialPort();
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                comPort.PortName = "COM3";
                comPort.Open();
            }
    
    
    Given this program, load it, make sure COM3 has something connected, while it is connected, unplug the line and then close the program, the UnauthorizedAccessException will be thrown.
  • viernes, 06 de noviembre de 2009 18:08xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I tried GC.ReRegisterForFinalize and GC.SuppressFinalize but the error is still showing up.
  • viernes, 06 de noviembre de 2009 18:13Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    The *actual* hardware interaction is probably being done on another thread. 
    I believe that the port itself generates the thread, not you.

    Subscribe to the Form_Closing event and call this stuff.

    port.Close();
    port.Dispose();

    Make sure the port is closed and disposed before the form closes.

    Mark the best replies as answers. "Fooling computers since 1971."
  • viernes, 06 de noviembre de 2009 18:52xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I have subscribed to the Form_Closing event and that, unfortunately, does not stop the error from popping up.
  • viernes, 06 de noviembre de 2009 19:40Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     

    And you say that you have nothing running on any threads that you created yourself?
    I have no means to reliably test serial ports.  This didn't throw any exceptions when the form was closing.


                serialPort2.Close();
                serialPort2.Dispose();
                while (serialPort2 != null)
                {

                }
                return;

    Mark the best replies as answers. "Fooling computers since 1971."
  • viernes, 06 de noviembre de 2009 19:40Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     

    I think the exception is thrown as the BaseStream of the SerialPort is being finalized when the plug is pulled. I've managed to overcome this error by adding a GC.SuppressFinalize call after calling SerialPort.Open, and then calling GC.ReregisterForFinalize (i think) method before i call SerialPort.Close. When doing this, i've never seen the exception occur again.

    Hope this helps

    Kev



    What about this?

    Mark the best replies as answers. "Fooling computers since 1971."
  • viernes, 06 de noviembre de 2009 21:31xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I tried to put GC.SuppressFinalizeand GC.ReregisterForFinalize to where Kev suggested but that exception still shows up.

    I also tried

                serialPort2.Close();
                serialPort2.Dispose();
                while (serialPort2 != null)
                {

                }
                return;

    but this just puts the application into the infinite loop when I try to close the form.

    And yes, the threads that I created wasn't doing anything at all. I tested both of your suggestions in the simply program I posted above, with only 1 button and open a fixed port.
  • viernes, 06 de noviembre de 2009 22:13Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    Then the port is never getting disposed.  My form closes with that while loop.
    Mark the best replies as answers. "Fooling computers since 1971."
  • sábado, 07 de noviembre de 2009 7:51ryanphillips112 Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
  • sábado, 07 de noviembre de 2009 17:50kevinwebster83 Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     

    Can you post any more of your code?

    I have had trouble with this exception before, however the GC.SuppressFinalize and GC.ReRegisterForFinalize DID fix the problem - i'm puzzled as to why it hasn't made a difference in this instance. Could be the driver i guess, as we use FTDI-based devices, although having said that, we have also used other non-FTDI devices as the code still works without exception.

    If it helps, i can post some of my code to try

    Kev

  • lunes, 09 de noviembre de 2009 20:55xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     Respondida
    OK, found out exactly what the problem is and the workaround

    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=140018

    NOTE: the  <legacyUnhandledExceptionPolicy enabled="1"/> posted by Microsoft no longer works with .NET Framework 3.5, I have yet to try any of other workout proposed.
    • Marcado como respuestaRudedog2Moderatorlunes, 09 de noviembre de 2009 21:21
    • Editadoxenoverse lunes, 09 de noviembre de 2009 21:23
    • Editadoxenoverse lunes, 09 de noviembre de 2009 21:26
    • Editadoxenoverse lunes, 09 de noviembre de 2009 21:25
    •  
  • lunes, 09 de noviembre de 2009 21:06kevinwebster83 Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I guess this is just one that Microsoft have swept under the carpet.
  • lunes, 09 de noviembre de 2009 21:20xenoverse Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    Can some one repost the link I posted and I'll mark that as an answer so anybody who has this problem in the future will have an easier time to find the solution. BTW, Microsoft said it should be fixed in the next major release of .NET Framework, which should be 4.0 with a scheduled release date of March 22, 2010. So this shouldn't be too long.

    Here is the link, if someone could post it again.

    https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=140018

  • lunes, 09 de noviembre de 2009 21:24Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    Work around?

    I think if you write a DLL that targets the .NET 2.0 framework that does all of that stuff, you should be good.
    Mark the best replies as answers. "Fooling computers since 1971."
  • martes, 10 de noviembre de 2009 18:19kevinwebster83 Medallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I know this post is already marked as answered but just as an update - the GC.SuppressFinalize and GC.ReRegisterForFinalize should be called passing the SerialPort instance BaseStream property as the parameter and not just the SerialPort instance.

    I've been having a play with this at work today and definitely no exception is generated with this code, whereas an exception is thrown without the code.

    Kev
  • martes, 10 de noviembre de 2009 19:17Rudedog2ModeratorMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuarioMedallas del usuario
     
    I know this post is already marked as answered but just as an update - the GC.SuppressFinalize and GC.ReRegisterForFinalize should be called passing the SerialPort instance BaseStream property as the parameter and not just the SerialPort instance.

    I've been having a play with this at work today and definitely no exception is generated with this code, whereas an exception is thrown without the code.

    Kev


    Thanks for the update.
    Your efforts are much appreciated.

    Mark the best replies as answers. "Fooling computers since 1971."