Search code examples
c#serial-portduplex

C# Receive and transmit serial bytes at the same time bug


I was working with my app when I suddenly realized that I could get an error with the serial port were I to transmit a byte at the time I would be reading one in. I started testing and within 5 seconds, bingo. I did not mis a received byte. But my program would stop working properly. We use a certain protocol and when it receives strange bytes it can get stuck. Something similar happens.

To send a byte I use pushbuttons, a pushbutton event calls a function which sends a byte.

serial.Write(toSend, 0, 1)

To read in I use the serial event which calls a backgroundworker which processes the data.

private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        lock (_lock)
        {
            rxBuffer += serial.ReadExisting();
        }
             try { backgroundWorker1.RunWorkerAsync(); } catch { } 
    }

console output

Bullseye set at (0,1)
9:44:52  << 0x80
9:44:52  << 0x3
9:44:52  << 0xA
Bullseye set at (1,1)
9:44:52  << 0x80
9:44:52  << 0x3
9:44:52  << 0xB
Bullseye set at (2,1)
9:44:52  << 0x80
9:44:52  0x95 >>
9:44:52  << 0x3
9:44:52  << 0xC   <-- bullseye didn't get set
9:44:53  << 0x80

the background worker also use the lock function.

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            //private void serialReceived(object s, EventArgs e)
            //{     
            while (rxBuffer.Length > 0)
            {
                lock (_lock)
                {
                    // textBox1.Text += rxBuffer[0];
                    byte b = Convert.ToByte(rxBuffer[0]);
                    string hexValue = b.ToString("X");

                    rxBuffer = rxBuffer.Remove(0, 1);

I don't know why the pushbutton events interferes with the background worker. I do see that I have all bytes received


Solution

  • I have finally solved most of my problems. It took me many hours of googling but I've found how I can use the beginInvoke(). Unlike the regular Invoke the beginInvoke seems not te be as slow. However when the machines sends too many bytes to my target device, it still freezes up

    So for now I got rid of the background worker and I use this. But I still prefer to use a background worker as it seems faster to me. But I cannot, I don't know how to.

     private void serial_DataReceived(object sender, SerialDataReceivedEventArgs e) // the Main serial receiving event.
        {
             lock (_lock)
             {
                rxBuffer += serial.ReadExisting();
             }
            serialReceived(rxBuffer);
        }
    
        private void serialReceived(string value)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new serialReceivedDelegate(serialReceived), new object[] { value });
            }
            else
            {
                lock (_lock)
                {