简体   繁体   中英

What is the best approach for serial data reception and processing using c#?

I am pretty new to coding with some experience in ASM and C for PIC. I am still learning high level programming with C#.

Question

I have a Serial port data reception and processing program in C#. To avoid losing data and knowing when it was coming, I set a DataReceived event and loop into the handling method until there were no more bytes to read.

When I attempted this, the loop continued endlessly and blocked my program from other tasks (such as processing the retrieved data) when I continuously received data.

I read about threading in C#, I created a thread that constantly checks for SerialPort.Bytes2Read property so it will know when to retrieve available data.

I created a second thread that can process data while new data is still being read. If bytes have been read and ReadSerial() has more bytes to read and the timeout (restarted every time a new byte is read from the serial) they can still be processed and the frames assembled via a method named DataProcessing() which reads from the same variable being filled by ReadSerial().

This gave me the desired results, but I noticed that with my solution (both ReadSerial() and DataProcessing() threads alive), CPU Usage was skyrocketed all the way to 100%!

How do you approach this problem without causing such high CPU usage?

public static void ReadSerial() //Method that handles Serial Reception
{
    while (KeepAlive) // Bool variable used to keep alive the thread. Turned to false
    {                 // when the program ends.
        if (Port.BytesToRead != 0)
        {
            for (int i = 0; i < 5000; i++) 
            {

             /* I Don't know any other way to 
                implement a timeout to wait for 
                additional characters so i took what 
                i knew from PIC Serial Data Handling. */

                if (Port.BytesToRead != 0)
                {
                    RxList.Add(Convert.ToByte(Port.ReadByte()));
                    i = 0;

                    if (RxList.Count > 20) // In case the method is stuck still reading
                        BufferReady = true; // signal the Data Processing thread to 
                 }                          // work with that chunk of data.

                 BufferReady = true; // signals the DataProcessing Method to work      
            }                        // with the current data in RxList.
        }         
    }    
}

I can not understand completely what you are meaning with the "DataReceived" and the "loop". I am also working a lot with Serial Ports as well as other interfaces. In my application I am attaching to the DataReceived Event and also reading based on the Bytes to read, but I dont use a loop there:

int bytesToRead = this._port.BytesToRead;
var data = new byte[bytesToRead];
this._port.BaseStream.Read(data , 0, bytesToRead);

If you are using a loop to read the bytes I recommend something like:

  System.Threading.Thread.Sleep(...);

Otherwise the Thread you are using to read the bytes is busy all the time. And this will lead to the fact that other threads cannot be processed or your CPU is at 100%.

But I think you don't have to use a loop for polling for the data if you are using the DataReceived event. If my undertanding is not correct or you need further information please ask.

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