0

need to process data received on a serial port in the background so that the decoded data can be used/displayed on the user form as it is received. Serial data message blocks may sometimes be received in multiple buffers. Therefore, the serial data buffers must be processed in the order they are received in order to insure that all message blocks are complete.

I am trying to process multiple serial data buffers in the order they are received using delegates in c#.

The method "public static void ReceiveSerialData(byte[] byteBuffer, int length)" is called from my ClassSerialPort when data is received.

I get the exception "System.NullReferenceException: 'Object reference not set to an instance of an object.'" on the line "caller.EndInvoke(out threadID, result);"

I have two questions:

  1. How do I correct the System.NullReferenceException exception?

  2. Will using delegates this way process multiple serial data buffers in the order they are received?

My code:

using ClassSerialPort;

using TheUserForm;

using System;

using System.Threading;

using System.Diagnostics;

using System.Text;


namespace TheUserForm

{

        class ClsReceiveSerialData
        {
            // SerialPort property
            private ClsSerialPort serialPort;
            public ClsSerialPort SerialPor`enter code here`t
            {
                get
                {
                    return serialPort;
                }

                set
                {
                    serialPort = value;
                }
            }

            public static void ReceiveSerialData(byte[] byteBuffer, int length)
            {
                int i;
                int threadID = 0;

    #if (TEST)
                StringBuilder sb = new StringBuilder(byteBuffer.Length * 2);
                i = 0;
                foreach (byte b in byteBuffer)
                {
                    //convert a byte to a hex string
                    sb.AppendFormat("{0:x2}", b);

                    i++;
                }

                //write the debuf string to the output window
                Debug.WriteLine("byteBuffer[" + (i - 1) + "] = " + sb.ToString());
    #endif
                // create an instance of a delegate class
                ClsProcessData ad = new ClsProcessData();

                // Create the delegate.
                AsyncProcessData caller = 
                   AsyncProcessData(ad.BeginProcessingData);


                // Initiate the asychronous call.
                IAsyncResult result = 
                caller.BeginInvoke(byteBuffer, length, out threadID, null, null);


                // Call EndInvoke to wait for the asynchronous call to complete,
                // and to retrieve the results.
                caller.EndInvoke(out threadID, result);
            }
        }

        class ClsProcessData
        {

            bool gotFirstFEcode = false;
            bool gotSecondFEcode = false;
            bool gotCtrlrCIV = false;
            bool okToSaveCommandBytes = false;
            bool gotEndOfMessageCode = true;
            byte[] commandData;
            int commandIndex = 0;

            public void BeginProcessingData(byte[] data, int byteCount, 
                                            out int threadId)
            {
                lock (this)
                {
                    int i;

                    threadId = Thread.CurrentThread.ManagedThreadId;

    #if (TEST)
                    Debug.WriteLine(
                     String.Concat("BeginProcessingData threadID = ",                         
                                    Convert.ToString(threadId)));
    #endif

                    //find a preamble
                    i = 0;
                    while (i < byteCount)
                    {
                        // have we completed processing the current message?
                        if (gotEndOfMessageCode)
                        {
                            //reset the preamble detection booleans
                            gotFirstFEcode = false;
                            gotSecondFEcode = false;
                            gotCtrlrCIV = false;
                            okToSaveCommandBytes = false;
                            gotEndOfMessageCode = false;
                        } // If

                        //can we save a command byte now?
                        if (okToSaveCommandBytes)
                        {
                            //go save a command byte
                            i = ExtractCommand(data, i, byteCount);

                            //reset the preamble detection booleans
                            gotFirstFEcode = false;
                            gotSecondFEcode = false;
                            gotCtrlrCIV = false;
                            okToSaveCommandBytes = false;
                            gotEndOfMessageCode = false;
                        } // If


                        //have we found the radio//s civ address?
                        if (gotCtrlrCIV && (data[i] == 
                            ClsConstants.CTRLR_DEFAULT_CIV_ADDR))
                        {
                            //we are ok to start saving command bytes
                            okToSaveCommandBytes = true;
                        } // If

                        //do we have both FE codes of the preamble and not 
                        another extraneous FE code in the buffer
                        if (gotSecondFEcode && (data[i] == 
                           ClsConstants.CTRLR_DEFAULT_CIV_ADDR))
                        {
                            gotCtrlrCIV = true;
                        } // If

                        if (gotFirstFEcode && (data[i] == 
                           ClsConstants.PREAMBLE_CODE))
                        {
                            gotSecondFEcode = true;
                        } // If

                        //do we have the first preamble code?
                        if ((data[i] == ClsConstants.PREAMBLE_CODE) &&           
                           (!gotSecondFEcode))
                        {
                            gotFirstFEcode = true;

                            //reset } // of message boolean
                            gotEndOfMessageCode = false;
                        } // If

                        //increment the array index
                        i++;

                    } // while
                }
            }

            // ExrtractCommand returns an updated index value
            private int ExtractCommand(byte[] data, int index, int byteCount)
            {
                int i = index;

                while ((i < byteCount) && (!gotEndOfMessageCode))
                {

                    if (data[i] == ClsConstants.END_OF_MESSAGE_CODE)
                    {
                        //set the end of message flag
                        gotEndOfMessageCode = true;

                        //Process the command
                        ProcessCommand(commandData, commandIndex);
                    }
                    else
                    {
                        //save a command byte
                        commandData[commandIndex] = data[i];

                        //increment to the next command index
                        commandIndex++;
                    } // If

                    //increment the data array index
                    i++;
                } // while

                return i;
            } // void

}
Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
Bob B
  • 1
  • 1
  • 4
    Possible duplicate of [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Camilo Terevinto Jul 21 '18 at 17:21
  • Camilo, thank you for your answer to my question about processing multiple buffers in the order they are received. I made the changes your code markup suggested. Everything is fine until I get to the line "// Create the delegate. AsyncProcessData caller = AsyncProcessData(ad.BeginProcessingData); That line gives the compile error "Non-invocable member 'AsyncProcessData' cannot be used as a method. That line appears to need a 'new' like my code had originally. – Bob B Jul 24 '18 at 14:48

0 Answers0