Search code examples
c#serial-portbackgroundworker

c# How to implement a background in this setup?


I have a nice and fancy C# program but the processing of the serially received bytes is way too slow. And I am thinking I can perhaps solve this using a background worker but I have no experience with it and all my earlier attemps failed.

private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            rxBuffer += serial.ReadExisting(); // add new bytes to the string 'rxBuffer'

            this.Invoke(new EventHandler(serialReceived));
        }

        private void serialReceived(object s, EventArgs e)
        {
            while (rxBuffer.Length > 0) // keep processing bytes until the string is empty
            {
                // textBox1.Text += rxBuffer[0];
                byte b = Convert.ToByte(rxBuffer[0]);
                string hexValue = b.ToString("X");

                rxBuffer = rxBuffer.Remove(0, 1); // removes the 'captured' byte from the string
                ..... 
                lots of code

This while loop is essentially 75% of my entire program. Incomming bytes
contoll UI elements, they can store or read from and to text files and send bytes back over the serial port, it simply can do about everything.

This systems works but it is far too slow. So I think moving the while loop in a background worker could solve it.

How can I implement a background worker in my current code setup? All my attempts so far failed.

EDIT: I want to add something which I just commented below. I thought that serial_DataReceived would be called with every single byte. There happens to be a delay of 2ms between 2 following received bytes in my application. ReadExisting() sometimes return more than 1 byte. So there is some kind of delay in the serial event. I have had this also in Qt but this was never a problem, I think it is ment as a feature to receive entire strings at once.

I personally think that the invoke() makes everything slow, but I have no prior experience with C# so I am just guessing, anyways I am open for any solutions.


Solution

  • this code seems to be the solution. I notice that my GUI runs signicantly smoother

    private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            rxBuffer += serial.ReadExisting();
    
            try { backgroundWorker1.RunWorkerAsync(); } catch { }
        }
    
    
        private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            //private void serialReceived(object s, EventArgs e)
            //{
            while (rxBuffer.Length > 0)
            {
                // textBox1.Text += rxBuffer[0];
                byte b = Convert.ToByte(rxBuffer[0]);
                string hexValue = b.ToString("X");
    
                rxBuffer = rxBuffer.Remove(0, 1);
    

    I tried using the isBusy() flag but it didn't work so I use the try and catch blocks instead.

    The serial_Datareceived nicely keeps adding new bytes to the string rxBuffer and the backgroundworker makes sure that every single byte of the rxString gets processed.

    EDIT: I have a problem, I cannot control my UI elements with the exception of a panel. I just found out. I am trying to acces the UI elements when I am still in a different thread.