线程正在持有串行端口人质

时间:2012-12-27 02:07:00

标签: c# multithreading serial-port conflict

  

新的更新:我们只是对外部框进行了一些调整以允许他接收,但不发送。当外部盒子静音,并且所讨论的串行端口没有接收数据时,此处描述的问题就消失了;也就是说,只要我们没有收到,我们就可以发送。那么,,这是我应该处理的错误或特征还是“已知问题”?

就此事项(非常)欢迎提供建议和指导。我在三个句子中的问题是......

  • 我可以从串口发送一组字节。

  • 串口开始接收,并继续接收。

  • 我无法发送另一组字节。

我得到的系统似乎没有响应。我告诉Visual Studio 2010打破所有。我的代码总是在一条线上点着一个弯曲的绿色箭头指向它。我将鼠标悬停在它上面,我看到的东西就是这样......

  

无法计算表达式,因为当前线程处于休眠,等待或加入

如果有任何专家阅读能够将这种复杂性扩散到更简单的英语解释中,那么这些人将长期成为我的朋友。

这是停滞不前的方法......

 public static void Tell_Box_To_Stop_Sending()
        {
            int Length;
            int StartingPosition;
            byte[] TheBytesToSend;

            Length = TheseBytesAreThe.Command_06_Stop_Data_Flood.Length;
            StartingPosition = 0;
            TheBytesToSend = TheseBytesAreThe.Command_06_Stop_Data_Flood;

            OurSpecificPorts.TheActivePortWeAreUsing.Write(TheBytesToSend, StartingPosition, Length);   ////// The green arrow is on this line

        }

这是用于打开端口的类。我应该把这个开放的端口带出这个类吗?

/**********************************************************************************
 * Class Name:          UART
 * 
 * Constructor:         Takes the string name, stores it, and does nothing else
 * 
 * Methods:             -- Open_TheActivePortWeWillUse --
 *                      
 **************************************************************************************/


class UART
{
    public SerialPort OurMainActiveSerialPort;                  

    public byte[] The_Immediate_Rx_Buffer;
    String The_Name_Of_The_Serial_Port;



    public UART(String ThePortNameTheCallerGaveUs)
    {
        The_Name_Of_The_Serial_Port = ThePortNameTheCallerGaveUs;
    }


    public static void send_command(byte[] The_Byte_Array, int Starting_Place, int Length)
    {
        ///OurMainActiveSerialPort.Write(The_Byte_Array, Starting_Place, Length);
        OurSpecificPorts.TheActivePortWeAreUsing.Write(The_Byte_Array, Starting_Place, Length);
    }


    /*****************************************************************
     * Method:      Open_TheActivePortWeWillUse
     * 
     * On Entry:    Caller gives us a name, in a string. C# and 
     *              Windows almost probably always use a format
     *              like "COM1" or "COM37" or some such scheme.
     *              
     *              Class:  OurSpecificPorts
     *              Item:   .TheActivePortWeAreUsing
     *              Has been defined as a serial port in the RegularVariables.cs file
     * 
     * 
     * Actions:     That serial port will be opened
     *              
     * 
     * On Exit:     The port will be connected, doing 8-N-1.
     * 
     *              
     *              We will store the port in a variable that's
     *              widely available to just about everybody.
     *              
     *              It will be in the class: OurSpecificPorts
     *              
     *              Its name will be: TheActivePortWeAreUsing 
     * 
     *              Another method, in this class, will take on
     *              the Event Handler which will respond to new
     *              bytes in the buffer.  (Don't be misled, this
     *              is not the UART FIFO buffer that you may be 
     *              thinking; but a buffer that Windows and C#
     *              arrange for us.)
     *              
     *              The name of that method will be...
     *              
     *              OurBackGroundSerialPortReceiver
     *              
     * 
     * Be Aware:    If this is a bluetooth connection, we get
     *              921600 bps irrespective of what we
     *              say we want for speed.
     * 
     * 
     *****************************************************************/
    public static void Open_TheActivePortWeWillUse(String Drone_StringNameFromUser)

                                                                                                    // First, open the port

        SerialPort TempSerialPort = new SerialPort (Drone_StringNameFromUser, int) SerialPortParameter.TheSerialPortSpeed);


        OurSpecificPorts.TheActivePortWeAreUsing = TempSerialPort;                                  // Now we have a name that anybody can see and use
        OurSpecificPorts.TheActivePortWeAreUsing.DataBits = 8;                                      
        OurSpecificPorts.TheActivePortWeAreUsing.Parity = Parity.None;                              
        OurSpecificPorts.TheActivePortWeAreUsing.StopBits = StopBits.One;                           


        OurSpecificPorts.TheActivePortWeAreUsing.DataReceived += new SerialDataReceivedEventHandler(OurBackGroundSerialPortReceiver);

        OurSpecificPorts.TheActivePortWeAreUsing.Open();                                            
    }

    /*************************************************************************************************
     * Method Name:         OurBackGroundSerialPortReceiver
     * 
     * Called By:           Windows internal things
     * 
     * Root Cause:          The UART generates an event
     * 
     * On Entry:            There is hopefully some data in the Uart's buffer
     * 
     *                      Windows and C# will set up two calling arguments
     *                      -- object sender
     *                      -- SerialDataReceivedEventArgs e 
     * 
     * Actions:             This method sets flags and semaphores to alert other parts of our code
     *                      of what we are doing, then it moves data out of the latest buffer that
     *                      the serial port provides, into another buffer. We'll use a trailer and
     *                      header scheme, much like our own box uses its interrupt handler with a
     *                      background/foreground scheme.
     *                      
     * On Exit:             Whatever was in the buffer is moved to the trailer/leader buffer which
     *                      other parts of the code will take and use
     *                      
     * Other References:    http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived
     * 
     *                      http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx
     *                      
     *                      http://msdn.microsoft.com/en-us/library/ms143549.aspx
     * 
     *                      Microsoft actually has example code there which makes sense.
     * 
     * 
     * ***********************************************************************************************/


    public static void OurBackGroundSerialPortReceiver(object sender, SerialDataReceivedEventArgs e )
    {
        SerialPort CurrentPort = (SerialPort)sender;            // Int routine gave is this in the arguments

        int LastByteInUartBuffer = CurrentPort.ReadBufferSize;
        int TheNumberOfBytes = CurrentPort.BytesToRead;
        byte[] inputData = new byte[TheNumberOfBytes];
        int WeGotThisMany = CurrentPort.Read(inputData, 0, TheNumberOfBytes);                

        int Dest;
        Dest = UartPlaceHolders.RxBufferLeader;                 // Will index into buffer for Chief dispatch

        int Source;                                             // Will index into Uart buffer to fish it out
        Source = 0;                                             // therefore, we start at zero

        int TopEdge;                                            // We'll calculate this here once instead of in the loops below
        TopEdge = (int)TheSizeOf.OneSecondsWorthOfData;         // This will tell us when to wrap around


        if (Dest < UartPlaceHolders.RxBufferTrailer)             // Half the time we'll have wrap-around
        {                                                        // If that's the case, then the trailer > the leader
            while (
                  (Dest < UartPlaceHolders.RxBufferTrailer)      // If we are wrapped, make sure we don't
                   &&                                            // overtake either the trailer or
                   (Dest < TopEdge)                              // go over the top edge
                   &&                                            // At the same time, make sure that
                   (Source <= LastByteInUartBuffer)              // we don't fish out more than is there
                   )
            {                                                    // Move bytes into buff for chief
                UartData.TheImmediateSecondOfData[Dest] = inputData[Source];
                Dest = Dest + 1;
                Source = Source + 1;                             
            }

            if (Source >= LastByteInUartBuffer)                 // Have we done all the bytes for this event ?            
            {                                                   // Yes, therefore we will update the leader
                UartPlaceHolders.RxBufferLeader = Dest;         // This tells us where to start next time

                aUartSemaphoreThatTells.WhatTheUartBackgroundRxIsDoing = (int)aValueWhichIndicatesThat.WeHaveReceivedSomeData;

                return;                                         // and we are done
            }
                                                                // //   Else no, more bytes so...
            else if (Dest >= TopEdge)                           // Did we wrap around ?
            {                                                   // Yes, so
                Dest = 0;                                       // wrap around to the start
                while (                                         // Now we do the same thing again
                      Dest < UartPlaceHolders.RxBufferTrailer   // C# and windows keep buffers at 4K max, 
                      &&                                        // so we will wrap only once
                      Source < LastByteInUartBuffer             // May not even need that other test
                      )                                         // This will finish the rest of the bytes
                {
                    UartData.TheImmediateSecondOfData[Dest] = inputData[Source];      // There they go
                    Dest = Dest + 1;
                    Source = Source + 1;
                }

                UartPlaceHolders.RxBufferLeader = Dest;         // This tells us where to start next time
                return;
            }

            else                                             // Dest is neither <, >, nor =, we have logic error
            {
                ErrorFlags.SerialPortErrorDescription = (int)AnError.ExistsInTheSerialPortBufferPointers;
                return;
            }

        }

                                                                 // We now take this case when the leader is up
                                                                 // ahead of, or equal to, the trailer. In that
                                                                 // case, we change the while loop to check for
                                                                 // the leader overtaking the top edge, but not
                                                                 // the trailer. Since the buffer will be about
                                                                 // 4x the size of what we get from the Uart it
                                                                 // is approximately guaranteed not to overtake
                                                                 // the trailer; do the arithmetic and you will
                                                                 // probably agree.
                                                                 // I am purposely using to large, similar, but
                                                                 // not completely identical schemes instead of
                                                                 // another "else" appended to the previous bag
                                                                 // of code. This will greatly improve debug.

        if (Dest >= UartPlaceHolders.RxBufferTrailer)            // Now, if the Trailer is ahead of the leader, here we go
        {                                                        
            while (
                   (Dest < TopEdge)                              // We still want to stop before we hit the top edge
                   &&                                            // At the same time, make sure that we don't go past...
                   (Source < LastByteInUartBuffer)               // ... the end of the Uart buffer
                   &&                                            // Nor do we want to go past...
                   (Source < TheNumberOfBytes)                   // ...the last byte the Uart gave us
                   )
            {
                UartData.TheImmediateSecondOfData[Dest] = inputData[Source];      // Move bytes into buff for chief
                Dest = Dest + 1;
                Source = Source + 1;
            }

            if (Source >= LastByteInUartBuffer)                  // Have we done all the bytes for this event ?
            {                                                    // Yes, therefore we will update the leader
                UartPlaceHolders.RxBufferLeader = Dest;          // This tells us where to start next time

                aUartSemaphoreThatTells.WhatTheUartBackgroundRxIsDoing = (int)aValueWhichIndicatesThat.WeHaveReceivedSomeData;

                return;                                          // and we are done
            }                                                    // //   Else no, we have more bytes to move, so...

            else if (Dest >= TopEdge)                            // Did we wrap around ?
            {                                                    // Yes, so...
                Dest = 0;                                        // wrap around to the start
                while (                                          // Now we do the same thing again
                      Dest < UartPlaceHolders.RxBufferTrailer    // C# and windows keep buffers at 4K max, 
                      &&                                         // so we will wrap only once
                      Source < LastByteInUartBuffer
                      )
                {
                    UartData.TheImmediateSecondOfData[Dest] = inputData[Source];
                    Dest = Dest + 1;
                    Source = Source + 1;
                }

                UartPlaceHolders.RxBufferLeader = Dest;          // This tells us where to start next time

                aUartSemaphoreThatTells.WhatTheUartBackgroundRxIsDoing = (int)aValueWhichIndicatesThat.WeHaveReceivedSomeData;

                return;
            }

            else                                                 // Dest is neither <, >, nor =, we have logic error, so debug this
            {
                ErrorFlags.SerialPortErrorDescription = (int)AnError.ExistsInTheSerialPortBufferPointers;
                return;
            }

        }

    }

}

我希望我没有包含太多代码。我在这里的前几个问题似乎总是导致人们要求查看更多代码。我想我已经在这里待了2周了,所以,感谢理解我糟糕的协议。

0 个答案:

没有答案