-1

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

bask185
  • 377
  • 1
  • 3
  • 12
  • The log tells a different story, though. You *are* seeing 0x3, 0xC, so it **has** been received, no? It seems your "trigger" functionality for figuring out when to "set bullseye" is thrown off by the sending. – Fildor Sep 12 '17 at 08:34
  • 2
    You would need to post more code to analyze the problem. Consider creating a [mcve]. – Fildor Sep 12 '17 at 08:39
  • 1
    It is very buggy code, that lock statement accomplishes nothing and the try/catch-em-all only stops the runtime from reminding you that it is buggy. Do avoid using two threads to get ahead. Either have DataReceived also process the data or don't use DataReceived at all and let the worker thread call Read(). The latter way produces code that is much easier to debug. – Hans Passant Sep 12 '17 at 09:38
  • Actually the lock statements solved another bug. Without them some of the received bytes would be processed twice, and my code was even more buggy than it is now. I will try to get rid of the serial received event that seems. This entire C# thread system is a big bug on it's own IMO. @Fildor I know, I saw it after I posted it, I think you answered when I was editing my OP, my bad :D – bask185 Sep 12 '17 at 11:30
  • @HansPassant I have moved everything under the background worker. I use runWorkercompleted to restart the backgroundworker. I am still having the exact same problem. Pushing a button disrupts the flow of the program – bask185 Sep 12 '17 at 12:25
  • You need a state machine. As Hans Passant pointed out, you should be able to process everything in the `DataReceived` event. You need the state machine to determine when its ok to send. You don't want to send until you've received your full message from the last send. See https://stackoverflow.com/a/38536373/2009197 – Baddack Sep 12 '17 at 17:54
  • I cannot do anything in the serialReceived event. Because sending bytes back is just 3% of the code, the rest of the 97% is updating UI elements and that cannot be done in the serialEvent, threads started in the serial event cannot update the UI – bask185 Sep 14 '17 at 05:49

1 Answers1

0

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)
            {
bask185
  • 377
  • 1
  • 3
  • 12