System Out Of Memory on custom 'Panda II' USBizi 100 application

Hi,
I am running out of memory and crashing the controller while running the program shown below. I am using the USBizi 100 module on a custom board. I am running two serial ports and three input interrupts. Are there any obvious problems with this program that jump out at anyone? I have a feeling it is related to my serial port DataReceived event handler, but have had trouble understanding some solutions in other posts. Should I be garbage collecting somewhere?

It seems sometimes that an interrupt causes the memory outage. Do these take up much memory when fired?

Thank you very much in advance,
Tom

using System;
using System.Threading;
using System.IO.Ports;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
namespace IndustrialIO
{
    public class Program
    {
        /// <summary>
        /// Stores Emergency Trip
        /// </summary>
        static bool emergencyBit = false;

        /// <summary>
        /// Sets up COM1 on the FEZ mini as the PC communication port
        /// </summary>
        static SerialPort COM1 = new SerialPort("COM1", 9600);
        
        /// <summary>
        /// Stores I2C device
        /// </summary>
        static I2CDevice myI2C;

        /// <summary>
        /// Create PCF8574 I/O Expander configuration
        /// </summary>
        static I2CDevice.Configuration PCF8574 = new I2CDevice.Configuration(0x38, 100);

        /// <summary>
        /// Create ADS1115 A/D Converter configuration
        /// </summary>
        static I2CDevice.Configuration ADS1115 = new I2CDevice.Configuration(0x48, 400);


        /// <summary>
        /// Set up Input Ports
        /// </summary>
        public static InputPort LDR = new InputPort((Cpu.Pin)FEZ_Pin.Digital.LDR, false, Port.ResistorMode.PullUp);
        public static InputPort DIN1 = new InputPort((Cpu.Pin)FEZ_Pin.Digital.An0, false, Port.ResistorMode.PullDown);
        public static InputPort DIN2 = new InputPort((Cpu.Pin)FEZ_Pin.Digital.An1, false, Port.ResistorMode.PullDown);
        public static InputPort DIN3 = new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.An2, false, Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeHigh);
        public static InputPort DIN4 = new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.Di12, false, Port.ResistorMode.PullDown, Port.InterruptMode.InterruptEdgeHigh);
        public static InputPort DIN5 = new InputPort((Cpu.Pin)FEZ_Pin.Digital.Di11, false, Port.ResistorMode.PullDown);
        public static InputPort DIN6 = new InputPort((Cpu.Pin)FEZ_Pin.Digital.Di13, false, Port.ResistorMode.PullDown);
        public static InputPort DIN7 = new InputPort((Cpu.Pin)FEZ_Pin.Digital.Di5, false, Port.ResistorMode.PullDown);
        public static InputPort DIN8 = new InputPort((Cpu.Pin)FEZ_Pin.Digital.Di6, false, Port.ResistorMode.PullDown);

        public static InputPort[] inputPorts = new InputPort[] {DIN1,DIN2,DIN3,DIN4,DIN5,DIN6,DIN7,DIN8};

        /// <summary>
        /// Set up output ports
        /// </summary>
        public static OutputPort DOUT1 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di21, false);
        public static OutputPort DOUT2 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di20, false);
        public static OutputPort DOUT3 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di23, false);
        public static OutputPort DOUT4 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di22, false);
        public static OutputPort DOUT5 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di25, false);
        public static OutputPort DOUT6 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di24, false);
        public static OutputPort DOUT7 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di27, false);
        public static OutputPort DOUT8 = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di26, false);
        public static OutputPort LED = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);

        public static OutputPort[] outputPorts = new OutputPort[] { DOUT1, DOUT2, DOUT3, DOUT4, DOUT5, DOUT6, DOUT7, DOUT8 };

        /// <summary>
        /// Sets up PWM ports
        /// </summary>
        public static PWM PWM1 = new PWM(PWM.Pin.PWM2);
        public static PWM PWM2 = new PWM(PWM.Pin.PWM1);

        /// <summary>
        ///  Create LCD
        /// </summary>
        public static AF10216A myLCD = new AF10216A("COM4");

        /// <summary>
        /// Set up dSpin items
        /// </summary>
        // Initialize flag and busy ports for all dSpin controllers
        public static InputPort flagPort = new InputPort((Cpu.Pin)FEZ_Pin.Digital.Di50, false, Port.ResistorMode.Disabled);
        public static InputPort busyPort = new InputPort((Cpu.Pin)FEZ_Pin.Digital.Di47, false, Port.ResistorMode.Disabled);

        public static UInt32 dSPIN_rx_data = 0;

        public static dSPIN_RegsStruct_TypeDef dSPIN_RegsStruct;

        public static dSpin myL6472 = null;

        /// <summary>
        /// X Axis configuration
        /// </summary>
        public static SPI.Configuration xAxisConfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di49,
            false, // Chip Select, active-low
            1000, // 1000 (nanoseconds?) setup time
            1000, // 1000 (nanoseconds?) hold time
            true, // Clock low on idle
            true, // Data valid on falling edge
            5000, // 5Mhz Clock Rate
            SPI.SPI_module.SPI2); //SPI device 2

        /// <summary>
        /// Y Axis configuration
        /// </summary>
        public static SPI.Configuration yAxisConfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di48,
            false, // Chip Select, active-low
            1000, // 1000 (nanoseconds?) setup time
            1000, // 1000 (nanoseconds?) hold time
            true, // Clock low on idle
            true, // Data valid on falling edge
            5000, // 5Mhz Clock Rate
            SPI.SPI_module.SPI2); //SPI device 2

        /// <summary>
        /// R Axis configuration
        /// </summary>
        public static SPI.Configuration rAxisConfig = new SPI.Configuration((Cpu.Pin)FEZ_Pin.Digital.Di51,
            false, // Chip Select, active-low
            1000, // 1000 (nanoseconds?) setup time
            1000, // 1000 (nanoseconds?) hold time
            true, // Clock low on idle
            true, // Data valid on falling edge
            5000, // 5Mhz Clock Rate
            SPI.SPI_module.SPI2); //SPI device 2

        /// <summary>
        /// Default method
        /// </summary>
        public static void Main()
        {
            // Initializes Motor Controllers
            InitializeMotors();

            // Write to LCD
            myLCD.SendCommand(AF10216A.Commands.FormFeed);
            Thread.Sleep(50);
            myLCD.Print("600-0061-2");
            Thread.Sleep(50);
            myLCD.SendCommand(AF10216A.Commands.CR);
            Thread.Sleep(50);
            myLCD.Print("Optics Placement");

            // Attach Event Handler to 'COM1'
            COM1.DataReceived += new SerialDataReceivedEventHandler(COM1_DataReceived);

            // Open Com port
            COM1.Open();

            // Attach events to Estop & LC Inputs
            DIN3.OnInterrupt += new NativeEventHandler(DIN3_OnInterrupt);
            DIN4.OnInterrupt += new NativeEventHandler(DIN4_OnInterrupt);


            // Set outputs low
            WriteDigitalOutputs(0);

            //Turn on LED
            LED.Write(true);

            // Set PWM
            PWM1.Set(100, 50);

            PWM1.Set(100, 10);

            while (true)
            {

            }
        }

        /// <summary>
        /// Handes DIN4 Interrupt
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <param name="time"></param>
        static void DIN4_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            // Debounce
            Thread.Sleep(50);

            // Read Emergency Input
            if (DIN4.Read())
            {
                emergencyBit = true;
            }

        }

        /// <summary>
        /// Handles DIN3 Interrupt
        /// </summary>
        /// <param name="data1"></param>
        /// <param name="data2"></param>
        /// <param name="time"></param>
        static void DIN3_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            // Debounce
            Thread.Sleep(50);

            // Read Emergency Input
            if (DIN3.Read())
            {
                emergencyBit = true;
            }
        }

        /// <summary>
        /// Initializes Controller
        /// </summary>
        static void InitializeMotors()
        {
            // Create new controller
            myL6472 = new dSpin(xAxisConfig, busyPort, flagPort);

            // Program x registers
            L6472Setup(myL6472);

            // Get status and print
            dSPIN_rx_data = myL6472.dSPIN_Get_Status();

            // Set y axis
            myL6472.port.Config = yAxisConfig;

            // Program y registers
            L6472Setup(myL6472);

            // Get status and print
            dSPIN_rx_data = myL6472.dSPIN_Get_Status();

            // Set z axis
            myL6472.port.Config = rAxisConfig;

            // Program r registers
            L6472Setup(myL6472);

            // Get status and print
            dSPIN_rx_data = myL6472.dSPIN_Get_Status();
        }

        /// <summary>
        /// Handles Data Received by COM1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void COM1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                // Wait for full string
                Thread.Sleep(50);
                
                // set write buffer
                string bufferString = String.Empty;
                byte[] bufferWrite = null;

                // Set read buffer
                byte[] buffer = new byte[COM1.BytesToRead];

                COM1.Read(buffer, 0, COM1.BytesToRead);

                char[] read = System.Text.Encoding.UTF8.GetChars(buffer);

                string readString = new string(read);

                string valueString = new string(new char[3] { read[3], read[4], read[5] });
                // determine command value
                int value = Convert.ToInt16(valueString);

                // determine what action to take...
                // Check for proper start character
                if (read[0] == '$')
                {
                    // Check for analog
                    if (read[1] == 'A' || read[1] == 'a')
                    {
                        // Check for input
                        if (read[2] == 'I' || read[2] == 'i')
                        {
                            // Read and print input
                            bufferString = ReadADC(Convert.ToInt16(read[3].ToString()), Convert.ToInt16(read[5].ToString()));
                        }

                    }
                    // Check for digital
                    else if (read[1] == 'D' || read[1] == 'd')
                    {
                        // Check for input
                        if (read[2] == 'I' || read[2] == 'i')
                        {
                            // Read inputs
                            bufferString = ReadDigitalInputs();
                        }
                        // Check for output
                        else if (read[2] == 'O' || read[2] == 'o')
                        {
                            // Write outputs
                            bufferString = WriteDigitalOutputs(value);
                        }
                    }

                    // Check for stepper motor control
                    else if (read[1] == 'E' || read[1] == 'e')
                    {
                        // Check for emergency read
                        if (read[2] == 'R' || read[2] == 'r')
                        {
                            bufferString = emergencyBit.ToString();
                        }
                        // Check for emergency write
                        else if (read[2] == 'W' || read[2] == 'w')
                        {
                            if (value == 0)
                            {
                                emergencyBit = false;
                                bufferString = emergencyBit.ToString();
                            }
                            else
                            {
                                emergencyBit = true;
                                emergencyBit.ToString();
                            }
                        }
                    }

                    // Check for stepper motor control
                    else if (read[1] == 'S' || read[1] == 's')
                    {
                        // Check for move command
                        if (read[2] == 'M' || read[2] == 'm')
                        {
                            // Determine # of steps
                            string stepString = new string(new char[6] { read[6], read[7], read[8], read[9], read[10], read[11] });
                            // determine command value
                            int steps = Convert.ToInt16(stepString);

                            // Determine Axis #
                            int axis = Convert.ToInt16(read[5].ToString());

                            // Determine Direction
                            if (read[3] == '1')
                            {
                                steps *= -1;
                            }

                            // Move Steps
                            bufferString = StepperMove(axis, steps);
                        }
                        
                        // Check For 'busy flag'
                        if (read[2] == 'B' || read[2] == 'b')
                        {
                            bool isBusy = busyPort.Read();

                            // Write Flag Value
                            bufferString = isBusy.ToString();
                        }

                        // Check For 'error flag'
                        if (read[2] == 'F' || read[2] == 'f')
                        {
                            bool isError = flagPort.Read();

                            // Write Flag Value
                            bufferString = isError.ToString();
                        }

                    }

                    // Create buffer string
                    bufferWrite = System.Text.Encoding.UTF8.GetBytes(bufferString + "\n");
                   // Return values
                   COM1.Write(bufferWrite, 0, bufferWrite.Length);
                }

            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// Reads the specified ADC channel and returns value
        /// </summary>
        /// <param name="inputNumber"></param>
        /// <returns></returns>
        public static string ReadADC(int resolution, int inputNumber)
        {
            try
            {
                // Dispose of old I2C
                if (myI2C != null)
                {
                    myI2C.Dispose();
                }

                // Set ADS1115 as I2C device
                myI2C = new I2CDevice(ADS1115);

                // Create transaction(s)
                I2CDevice.I2CTransaction[] xAction = new I2CDevice.I2CTransaction[1];

                // Build transaction bytes
                // Config byte 1
                byte config1 = (byte)(192 + (16 * inputNumber) + (2 * resolution) + 1);

                // Config byte 2
                byte config2 = 131;

                // create write buffer (we need three bytes)
                byte[] registerADS1115 = new byte[3] { 1, config1, config2 };
                // Create write transaction
                xAction[0] = I2CDevice.CreateWriteTransaction(registerADS1115);
                // excecute ADS1115 setup
                myI2C.Execute(xAction, 1000);

                // Wait for conversion
                Thread.Sleep(15);

                // Set to conversion register
                registerADS1115 = new byte[1] { 0 };
                xAction[0] = I2CDevice.CreateWriteTransaction(registerADS1115);
                // Execute set to conversion
                myI2C.Execute(xAction, 1000);

                // create read buffer
                byte[] readADS1115 = new byte[2];
                // Read ADC values
                xAction[0] = I2CDevice.CreateReadTransaction(readADS1115);
                myI2C.Execute(xAction, 1000);

                // return values
                return (readADS1115[0] * 256 + readADS1115[1]).ToString();
            }
            catch (Exception exp)
            {
                return exp.Message;
            }
        }

        /// <summary>
        /// Writes proper digital outputs
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        public static string WriteDigitalOutputs(int outputs)
        {
            try
            {
                int registerValue = 0;
                int[] intArray = new int[8];
                bool[] boolArray = new bool[8];

                // Check to see which command is given
                // Write outputs
                if (outputs <= 255)
                {
                    // convert to binary array
                    int value = outputs;

                    for (int i = 0; i < 8; i++)
                    {
                        intArray[7 - i] = value >> (7 - i);
                        value -= intArray[7 - i] * (1 << (7 - i));
                        
                        //populate bool array
                        if (intArray[7-i] == 0)
                        {
		                    boolArray[7-i] = false;
                        }
                        else
                        {
                            boolArray[7-i] = true;
                        }
                    }

                    // change output states to match
                    for (int i = 0; i < boolArray.Length; i++)
			        {
                        outputPorts[i].Write(boolArray[i]);
			        }
                        

                    // Send back register value
                    registerValue = outputs;
                }

                // Read outputs
                else if (outputs == 999)
                {
                    // convert output values into an integer
                    foreach (int i in intArray)
                    {
                        registerValue += intArray[i] << i;
                    }
                }

                // Return register value
                return registerValue.ToString();
            }
            catch (Exception exp)
            {
                return exp.Message;
            }
        }

        /// <summary>
        /// Returns digital input values
        /// </summary>
        /// <param name="inputs"></param>
        /// <returns></returns>
        public static string ReadDigitalInputs()
        {
            try
            {
                // Sets up inputs boolean
                bool[] inputs = new bool[8];

                // read inputs
                inputs[0] = DIN1.Read();
                inputs[1] = DIN2.Read();
                inputs[2] = DIN3.Read();
                inputs[3] = DIN4.Read();
                inputs[4] = DIN5.Read();
                inputs[5] = DIN6.Read();
                inputs[6] = DIN7.Read();
                inputs[7] = DIN8.Read();

                int input = 0;
                int total = 0;

                // Concatenate inputs into an integer 0-255
                for (int i = 0; i < inputs.Length; i++)
                {
                    // Check boolean, and convert to binary
                    if (inputs[i])
                    {
                        input = 1;
                    }
                    else
                    {
                        input = 0;
                    }

                    total += input * (int)System.Math.Pow(2, i);
                }

                // Return register value
                return total.ToString();
            }
            catch (Exception exp)
            {
                return exp.Message;
            }
        }

        /// <summary>
        /// Sets up dSpin controller
        /// </summary>
        /// <param name="myL6472"></param>
        public static void L6472Setup(dSpin myL6472)
        {
            // Reset device
            myL6472.dSPIN_Reset_Device();

            /* Acceleration rate settings to 466 steps/s2, range 14.55 to 59590 steps/s2 */
            dSPIN_RegsStruct.ACC = (UInt16)((UInt32)(((10) * 67.108864) + 0.5)); //AccDec_Steps_to_Par
            /* Deceleration rate settings to 466 steps/s2, range 14.55 to 59590 steps/s2 */
            dSPIN_RegsStruct.DEC = (UInt16)((UInt32)(((10) * 67.108864) + 0.5)); //AccDec_Steps_to_Par
            /* Maximum speed settings to 488 steps/s, range 15.25 to 15610 steps/s */
            dSPIN_RegsStruct.MAX_SPEED = ((UInt16)(((10000) * 0.065536) + 0.5)); // MaxSpd_Steps_to_Par(488)
            /* Minimum speed settings to 0 steps/s, range 0 to 976.3 steps/s */
            dSPIN_RegsStruct.MIN_SPEED = ((UInt16)(((0) * 4.194304) + 0.5)); // MinSpd_Steps_to_Par(0)
            /* Full step speed settings 252 steps/s, range 7.63 to 15625 steps/s */
            dSPIN_RegsStruct.FS_SPD = ((UInt16)((252) * 0.065536)); // FSSpd_Steps_to_Par(252)
            /* Hold duty cycle (torque) settings to 10%, range 0 to 99.6% */
            dSPIN_RegsStruct.TVAL_HOLD = (byte)Macro.TorqueToPar(500); // Kval_Perc_to_Par(10)
            /* Run duty cycle (torque) settings to 10%, range 0 to 99.6% */
            dSPIN_RegsStruct.TVAL_RUN = (byte)Macro.TorqueToPar(1500); // Kval_Perc_to_Par(10)
            /* Acceleration duty cycle (torque) settings to 10%, range 0 to 99.6% */
            dSPIN_RegsStruct.TVAL_ACC = (byte)Macro.TorqueToPar(1500); // Kval_Perc_to_Par(10)
            /* Deceleration duty cycle (torque) settings to 10%, range 0 to 99.6% */
            dSPIN_RegsStruct.TVAL_DEC = (byte)Macro.TorqueToPar(1500); // Kval_Perc_to_Par(10)
            /* Overcurrent threshold settings to 2625mA */
            dSPIN_RegsStruct.OCD_TH = (byte)dSPIN_OCD_TH_TypeDef.dSPIN_OCD_TH_2625mA;
            /* Step mode settings to 16 microsteps */
            dSPIN_RegsStruct.STEP_MODE = (byte)dSPIN_STEP_SEL_TypeDef.dSPIN_STEP_SEL_1_16;
            /* Alarm settings - all alarms enabled */
            dSPIN_RegsStruct.ALARM_EN = (byte)(dSPIN_ALARM_EN_TypeDef.dSPIN_ALARM_EN_OVERCURRENT | dSPIN_ALARM_EN_TypeDef.dSPIN_ALARM_EN_THERMAL_SHUTDOWN
                | dSPIN_ALARM_EN_TypeDef.dSPIN_ALARM_EN_THERMAL_WARNING | dSPIN_ALARM_EN_TypeDef.dSPIN_ALARM_EN_UNDER_VOLTAGE | dSPIN_ALARM_EN_TypeDef.dSPIN_ALARM_EN_SW_TURN_ON | dSPIN_ALARM_EN_TypeDef.dSPIN_ALARM_EN_WRONG_NPERF_CMD);
            /* Internal oscillator, 2MHz OSCOUT clock, supply voltage compensation disabled, *
             * overcurrent shutdown enabled, slew-rate = 290 V/us, PWM frequency = 15.6kHz   */
            dSPIN_RegsStruct.CONFIG = ((UInt16)dSPIN_CONFIG_OSC_MGMT_TypeDef.dSPIN_CONFIG_INT_16MHZ_OSCOUT_2MHZ) |
                ((UInt16)dSPIN_CONFIG_SW_MODE_TypeDef.dSPIN_CONFIG_SW_HARD_STOP) |
                ((UInt16)dSPIN_CONFIG_EN_VSCOMP_TypeDef.dSPIN_CONFIG_VS_COMP_DISABLE) |
                ((UInt16)dSPIN_CONFIG_OC_SD_TypeDef.dSPIN_CONFIG_OC_SD_ENABLE) |
                ((UInt16)dSPIN_CONFIG_POW_SR_TypeDef.dSPIN_CONFIG_SR_290V_us) |
                ((UInt16)dSPIN_CONFIG_F_PWM_INT_TypeDef.dSPIN_CONFIG_PWM_DIV_2) |
                ((UInt16)dSPIN_CONFIG_F_PWM_DEC_TypeDef.dSPIN_CONFIG_PWM_MUL_1);

            /* Program all dSPIN registers */
            myL6472.dSPIN_Registers_Set(ref dSPIN_RegsStruct);
        }

        /// <summary>
        /// Moves stepper motor the required number of steps
        /// </summary>
        /// <param name="axis"></param>
        /// <param name="steps"></param>
        /// <returns></returns>
        public static string StepperMove(int axis, int steps)
        {
            // Select correct axis
            if (axis == 1)
            {
                myL6472.port.Config = xAxisConfig;
            }
            else if (axis == 2)
            {
                myL6472.port.Config = yAxisConfig;
            }
            else if (axis == 3)
            {
                myL6472.port.Config = rAxisConfig;
            }
            else
            {
                return "Incorrect Axis Specified";
            }

            // Determine Direction
            dSPIN_Direction_TypeDef dir = dSPIN_Direction_TypeDef.FWD;

            // If steps are negative, reverse
            if (steps < 0)
            {
                dir = dSPIN_Direction_TypeDef.REV;
            }
                     
            // Get status and print
            dSPIN_rx_data = myL6472.dSPIN_Get_Status();
            Debug.Print(dSPIN_rx_data.ToString());

            Thread.Sleep(10);

            // Move motor forward
            myL6472.dSPIN_Move(dir, (uint)System.Math.Abs(steps));

            Thread.Sleep(10);

            //Wait untill not busy - busy pin test 
            while (myL6472.dSPIN_Busy_HW() == 0) ;

            return "Move Complete";
        }

    }
}

2 things. This is very bad


while (true)
            {
 
            }

use Thread.Sleep(-1);

Also, I would have a thread that reads the serial data in a loop and uses a fixed buffer instead of allocating and freeing a buffer every time serial event is fired.

Another version of the software has the

white (true)
{
}

blinking an LED to show the controller is cycling normally. Should I do this in a separate thread?

Does Thread.Sleep(-1) go inside the while loop, or replace it completely?

Does anyone have an example of how that separate thread might look in this application?

Thank you.
Tom

@ tommyvdp - It should replace your empty while(true) loop at the end of the main method.

just to add a little more…

thread.sleep(timeout.infinite) is the best representation here because it articulates what is going on.

If you leave your LED flashing in your main() in a while(true) loop, that is fine; you don’t need a thread.sleep(timeout.infinite) at the end of the main() after the loop as it will never be run. You could also replace the LED flash with just a thread.sleep(200) or similar just so there isn’t a spinning loop or the risk of a terminating app.

To help debug this, you probably need breakpoints in the datarecieved handler and look at what is going on; as Gus says, reallocating stuff every time the handler is called will be costly and lead to fragmentation which you might be able to get around if you force GC to run.

But I think your approach is not good; datarecieved is meant to be a get-in, unbuffer-the-data, get-out-as-quick-as-possible routine. You do a sleep in it - not something I think is good practice. You really want to just unbuffer the data, and deal with it all outside the handler. If your data is structured (always a known number of bytes or cleanly terminated, and/or you control the sending device so you can create a “protocol”, then this can be somewhat easy; your handler just looks to see if it got the magic character (say “]” or something) and if so, set a global flag; your main() can just do a sleep until it sees the flag being set then it can parse the command and do what it’s told.

@ Brett -

Thank you,
I am used to using DataRecieved in C# on a PC with a large method inside it with no problems due to the whopping amounts of memory available. The data is structured with a ‘$’ beginning it. It is acting as the physical I/O for a PC based production test system. I will try your advice.
Thanks,
Tom