简体   繁体   中英

Reading data from serial Port is loosing packages

Hello i created a program which reads serial data from a scoreboard, then depending on the string the program separates the data into different boxes on the form and then to different txt files.The purpose of this, is to use those txt files for livestreaming purposes in basketball games. It's the first time i work with serial data and i am not a very experienced programmer.

My problem, as the title of this post suggests is that every now and then without any reason i am loosing some packages. This is happening randomly, for example in 10 second period i could 1 package while the next one none or 4.

private void ReadData() 
        {
            Thread MyThread = null;
           
            {
                try
                {
                     ThreadStart ThreadMethod = new ThreadStart(ReadFromPort);
                     MyThread = new Thread(ThreadMethod);
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to create thread! " + e.Message);
                    return;
                }
                try
                {
                    MyThread.Start();

                }
                catch (Exception e)
                {
                    Console.WriteLine("The thread failed to start! " + e.Message);
                }
            }
        }

        //Recieves data and write them on textbox (optionally on a txt)
        private void ReadFromPort()
        {
            
            while (Receiver == true)
            {
                try
                {
                    
                    int count = ComPort.BytesToRead;
                    System.Windows.Forms.Application.DoEvents();
                    
                   
                    byte[] data = new byte[count];
                    ComPort.Read(data, 0, data.Length);           
                    currentMessage = Combine(currentMessage, data);
                    ReceivedData = (BitConverter.ToString(data)); 
                                   
                    if (count > 0)
                    {
                        if (chBoxUpdate.Checked)
                        {
                            DataType = count;
                            tempData = ReceivedData;
                            this.Invoke(new EventHandler(DisplayText));
                            if (chboxTxt.Checked)
                            {
                                this.Invoke(new EventHandler(ExportData));
                            }
                        }
                        else if (chBoxPrevious.Checked)
                        {
                            DataType = count;
                            tempData = ReceivedData;
                            this.Invoke(new EventHandler(ClearData));
                            this.Invoke(new EventHandler(DisplayText));
                            if (chboxTxt.Checked)
                            {
                                this.Invoke(new EventHandler(ExportData));
                            }
                        }
                        
                    }
                }
                catch (Exception e)
                {

                }
            }
        }

        //Displays Text
        private void DisplayText(object sender, EventArgs e)
        {
            string temp;
            Console.WriteLine(tempData+ " (" + tempData.Length.ToString() + ")");
           
            try
            {
                if (tempData.Length == 38)// && ReceivedData.Substring(12, 5) == "03-02")
                {
                    if (tempData.Substring(12, 5) == "03-02")
                    {
                        DataText.AppendText(tempData.Substring(24, 8));
                        DataText.AppendText("\n");
                        Blink.Text = "Reading...";
                        timer1.Start();
                        timer1.Enabled = true;
                    }
                }
                else
                if (tempData.Length == 35)   
                {
                    if (tempData.Substring(12, 5) == "45-02")
                    {
                        AttackTime.AppendText(tempData.Substring(24, 5));
                        Blink.Text = "Reading...";
                        AttackTime.AppendText("\n");
                        timer1.Start();
                        timer1.Enabled = true;
                    }
                }
                else
                if (tempData.Length == 29)  
                {
                    if (tempData.Substring(12, 5) == "03-36")  
                    {
                        HomeScore.AppendText(tempData.Substring(21, 2));
                        Blink.Text = "Reading...";
                        HomeScore.AppendText("\n");
                        timer1.Start();
                        timer1.Enabled = true;
                    }
                    else
                    if (tempData.Substring(12, 5) == "03-46")  
                    {
                        AwayScore.AppendText(tempData.Substring(21, 2));
                        Blink.Text = "Reading...";
                        AwayScore.AppendText("\n");
                        timer1.Start();
                        timer1.Enabled = true;
                    }
                }
            }
            catch (ArgumentOutOfRangeException)
            {

            }
        }


Keep in mind that tempData and ReceivedData are the same here and as the programs appears now there's not any particular reason to set tempData=ReceivedData.This is a part of a different,older code i used in the begining which i never changed but it doesn't effect the program.

At first i am using a thread to enable the ReadFromPort then if the program finds that there are available data in line it displays them with the DisplayText and it's using the ExportData to export the data to a txt.I think the problem is somewhere there but as i am not very experienced i can't tell where.

Are there any suggestions on how to improve my code? If you more details or information i can provide them.

You are using Invoke , this blocks the caller thread until the event has been processed, and since you are updating the UI this can take some time. This probably causes some buffer to overflow and data to be discarded. So you should do as little work as possible on the reading thread.

There are a few alternatives

  1. Put the data on a concurrentQueue , and let the UI thread have a timer that periodically triggers a method that reads from the queue and updates the UI.
  2. Put the data on a concurrentQueue , wrapped in a blocking collection , have another background thread iterate over the blocking collection, using GetConsumingEnumerable , and post the result to the main thread once done. This would be suitable if there is significant processing to be done.
  3. Use BeginInvoke to post the received data to the main-thread, this does not wait for the call to complete, but probably have slightly higher overhead that the previous alternatives. I would recommend not accessing any UI properties from the background thread, since by default no property of a UI class is threadsafe. Even if you might get away with it if you are only reading, I would not take the chance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM