none
bug in serialport.close() ?

    Question

  • Hi !

    Here is my problem ...

    I developped in C# a class heriting from SerialPort. It contains functions structured like this :
    serialPort.open();
    ....write....read.... ans so on;
    serialPort.close();

    I use a timer to run theses functions every miliseconds.

    After a time, the application freeze. When i debug using "break all", i see a green arrow pointing serialPort.close(). When i press F11 to go to the next instruction, i can't see any yellow arrow. The green one disappear and my application stay freezed. When i break all a second time, the green arrow reappear pointing the serialPort.close() function etc.... The only solution is to stop debugging and run my application again.

    Could anybody tell me where does it come from ??

    Thanks for all !!!


    Monday, June 19, 2006 1:14 PM

Answers

  • OK, it is not DiscardOutBuffer().  The documentation for the Close() method specifically warns that we should "wait for some amount of time" before opening the port again.  The SerialPort class no doubt needs some time for threads to exit.

    Well, let's punt and avoid opening and closing the port over and over again.  Call Open() when you initialize the port and Close() when your program exits.  This is the normal use for a SerialPort object and might avoid some obscure deadlock inside the class.

    If you want a better answer, you'll need to tell us what exceptions are being raised...

    Wednesday, June 21, 2006 12:44 PM
    Moderator

All replies

  • I have moved this thread here from Windows Forms forum. Hopefully you'll get a response from your question.

    Regards,

    -chris
    Tuesday, June 20, 2006 9:39 AM
    Moderator
  • This is probably caused by the serial port still having bytes to send and the device has turned off the handshake.  Check the BytesToWrite property value.  Use DiscardOutBuffer() to throw away any unsent characters.

    Tuesday, June 20, 2006 2:32 PM
    Moderator
  • I thought it wa something like that too but i tried everything ans the problem's stil there. First, i thought it was due to multitasking problems but then i noticed i had the problem only with a single loop. Here is the code.

    while(true)
    {
    read_FDP();
    }

    public Int16 read_FDP(byte adresse)
    {
    try { Close(); }
    catch { };

    if (!IsOpen) //If port closed
    {

    try { Open(); }
    catch (Exception) { }

    //If port is opened
    if (IsOpen)
    {
    DiscardInBuffer(); //discard the buffer

    try { Write(SOF_string); } //start of frame
    catch(Exception){return (-1);}

    trame_out[0] = 13; //command type
    trame_out[1] = adresse; //adress

    try{Write(trame_out, 0, 2);}
    catch(Exception){ return (-1);}

    try { Write("!"); } //end of frame
    catch (Exception) { return 1; }

    //on vérifie si ca a fonctionné
    try { Read(trame_in, 0, 3); } // Waiting for 3 chars
    catch (Exception)
    {
    DiscardInBuffer();
    DiscardOutBuffer();

    try { Close(); }
    catch { }; //Close the port
    return (-1); //no response
    }
    try { Close(); }                         edit :                //GENERALLY THIS ONE IS THE PROBLEM
    catch { }; //Close the port

    if (trame_in[0] == '!' && trame_in[1] == 13)
    {
    return trame_in[2]; // Return the read data
    }
    else
    return (-3);
    }
    }
    return (-2);
    }

    Impossible to make it loop more than a few minutes.

    Does anyone have a suggestion ?

    Thanks for your help !

    @@@
    Tuesday, June 20, 2006 8:04 PM
  • A bunch of Close() calls, which one does it hang on?  You are also silently discarding exceptions, at least use Debug.Print to know what is going wrong.  Also show us the code that initializes the SerialPort instance.

    Tuesday, June 20, 2006 8:24 PM
    Moderator
  • Yes you're right for the exceptions but this soft is only for a demonstration. I normally don't need them.

    I will make some tries with printing.

    I initialize the serialport just with that :

    BaudRate = 921600;         //Not a problem it uses a cdc driver
    ReadTimeout = 300;
    WriteTimeout = 300;

    Thanks for your help



    Tuesday, June 20, 2006 8:45 PM
  • The same problem, waiting solution...
    Wednesday, June 21, 2006 9:42 AM
  • are we the only ones to have that problem and not the solution ?

    Does anyone have others suggestions ?

    Thanks a lot ;-)


    Wednesday, June 21, 2006 10:40 AM
  • Which Close() does it hang on?

    Wednesday, June 21, 2006 11:02 AM
    Moderator
  • I edited the sample code...

    Thanks !!
    Wednesday, June 21, 2006 11:22 AM
  • OK, it is not DiscardOutBuffer().  The documentation for the Close() method specifically warns that we should "wait for some amount of time" before opening the port again.  The SerialPort class no doubt needs some time for threads to exit.

    Well, let's punt and avoid opening and closing the port over and over again.  Call Open() when you initialize the port and Close() when your program exits.  This is the normal use for a SerialPort object and might avoid some obscure deadlock inside the class.

    If you want a better answer, you'll need to tell us what exceptions are being raised...

    Wednesday, June 21, 2006 12:44 PM
    Moderator
  • Yes i saw that in the docs. Another person told me the same. I will have to change my code.

    Thanks for your help ! I'll give some results later...

    Thanks again !!!


    Wednesday, June 21, 2006 1:33 PM
  • Everything works...

    Thanks a lot.
    Thursday, June 22, 2006 7:52 AM
  • I have the same issue. I have a pocket pc application that uses the IR port in raw mode using the serialport component from .net. It works most of the time but sometimes the port stops working
    At the beginning i opened the port when opening the windows form and closed the port when leaving the form but then i tried to open and close the port after getting time outs on the comunication with a custom device and it seems to improve somehow the stablility of the code. However, now it hangs sometimes on the close call as described in the previous posts
    No exceptions are thrown and when stoping the process in the debugger it is at the  close call.

    what is the correct sequence to flush and reset the port?
    Sunday, March 18, 2007 6:46 PM
  • I have the same issue. I have a pocket pc application that uses the IR port in raw mode using the serialport component from .net. It works most of the time but sometimes the port stops working
    At the beginning i opened the port when opening the windows form and closed the port when leaving the form but then i tried to open and close the port after getting time outs on the comunication with a custom device and it seems to improve somehow the stablility of the code. However, now it hangs sometimes on the close call as described in the previous posts
    No exceptions are thrown and when stoping the process in the debugger it is at the  close call.

    what is the correct sequence to flush and reset the port?
    Sunday, March 18, 2007 6:49 PM
  • This thread, any several others, document this problem with the SerialPort class.  The Close() method suffers from a deadlock that seems to be triggered by not letting enough time expire between closing and re-opening a port.  A subsequent Close() hangs.  The documentation warns about this but gives no details nor suggestions on how to avoid the deadlock.

    Given what is known sofar, I'd recommend you try to get your app stable without repeatedly closing the port.  Or by sleeping for a while after closing the port so I/O completion threads get enough time to terminate.
    Sunday, March 18, 2007 7:37 PM
    Moderator
  • It is extremely hard to find any good below-the-hood information about the serial port, but it seems that the serial port graps a thread from the thread pool when a port is opened. This thread is used at least to handle the receive buffer (DataReceived event etc.), but other parts of the serial port are apparently still using the UI thread - at least you do not get any cross-thread error if you write directly to a control on the UI thread from a subroutine, which handles the PinChanged event.

    I usually put an Application.DoEvents() and a Sleep(200) statement after a Close() statement to empty the message queue and give the system some time to release the thread to the pool, and it seems to work, but the parts of the SerialPort, which runs on the UI thread, are of course not affected by the Sleep() statement so maybe this statement is not necessary?

    Monday, March 19, 2007 7:51 AM
  • I am developing an application on pocket pc to communicate with a custom device on the IR port using the .net serial port component. The communication protocol requires a cycle of send command form PPC and receive response from device. It is possible that the device will not answer or that the user is not pointing to IR port. I am using a System timer to generate a timeout event when there is no response from device. This scheme works most of the time but is fragile
    On the handler of the timeout event I tried to close and open the port because it seems that after some time the port stops working. but then the code hangs on the close call. I added a thread.sleep but then i got race conditions and some variables changed values at unexpected points of the code. is there a best pattern for  command-response serial port communication using  the serial  port component?
    Monday, March 19, 2007 11:16 PM
  • Why don't you just set YourSerialPort.WriteTimeout to the wanted timeout time and then send in a Try statement? In VB it looks like this:

    YourSerialPort.WriteTimeout = 5000    ' 5 sec timeout

    Try

        YourSerialPort.Write(...)

    Catch ex As Exception

        MsgBox(ex.Message)

    End Try

     

    Tuesday, March 20, 2007 11:31 AM
  • the  write timeout does not occur writing to to the IR  port  but at a higher level on the application  for example sending info command  and receving header+data on complete and correct form
    Tuesday, March 20, 2007 8:00 PM
  • In that case, a ReadTimeout may do it.
    Wednesday, March 21, 2007 7:00 AM
  • using synchronus read with readByte and try catch on timeout exception simplified the code and gives a more stable solution

    thank you
    Friday, March 23, 2007 6:50 AM
  • Can I get a code snippet of how you did this. I am having similiar issues. Thanks in advance
    Thursday, May 17, 2007 2:16 PM
  • This is the function to process commands

    linkPort is a serialport object

    if you have any questions feel free to ask

     

    /// <summary>

    /// Send an instruction to the bar

    /// </summary>

    /// <param name="command">Request to be send to the bar</param>

    public ReceivedStatus Send(Command command)

    {

    OpenPort();

    Bar.instance.Reset();

    BarInstruction = command;

    OnSendCommand(new SendCommandEventArgs(command, DateTime.Now, status));

    Next();

    switch (command)

    {

    case Command.Configure:

    StringBuilder configure = new StringBuilder(string.Empty);

    configure.Append(ConfigureCommand);

    configure.Append(name);

    configure.Append("\r");

    receivedConfigureBlock = null;

    Send(configure.ToString());

    break;

    case Command.Info:

    receivedInfoBlock = null;

    Send(InfoCommand);

    break;

    case Command.Inf2:

    receivedInf2Block = null;

    Send(Inf2Command);

    break;

    case Command.Version:

    receivedVersionBlock = null;

    Send(VersionCommand);

    break;

    case Command.TestMap:

    receivedTestMapBlock = null;

    Send(TestMapCommand);

    break;

    default:

    break;

    }

    for (int i = 0; i < commandSize[(int)command]; i++)

    {

    if ((status > CommandStatus.Standby) &&

    (status < CommandStatus.Received))

    {

    try

    {

    Parse((byte)linkPort.ReadByte());

    }

    catch (TimeoutException)

    {

    Timeout();

    break;

    }

    }

    else

    {

    break;

    }

    }

    if ((status!=CommandStatus.Received)&&(status!=CommandStatus.Timeout))

    {

    Timeout();

    FlushPort();

    ClosePort();

    Thread.Sleep(2000);

    OpenPort();

    received = ReceivedStatus.Error;

    }

    return received;

    }

    Thursday, May 17, 2007 11:19 PM
  • Hello Brixi69,

     

    How did you make it work?

    i am facing the same problem in my code,

     

    Please reply.

    Thanks and Regards.

    Amarjeet.

     

    • Proposed as answer by Emre BAYRAM1 Monday, January 2, 2012 7:33 AM
    Wednesday, August 22, 2007 6:04 AM
  • Use Control.BeginInvoke() instead of Control.Invoke() in your DataReceived event handler.  Your app will deadlock when you call Close() on your UI thread but the SerialPort is still waiting for a Control.Invoke() to complete.  Calling Close() on another thread is another possible workaround, as is not calling it at all.
    Wednesday, August 22, 2007 6:18 AM
    Moderator