System.IO.Ports.SerialPort and Multithreading

后端 未结 4 667
清酒与你
清酒与你 2021-02-02 04:42

I have some SerialPort code that constantly needs to read data from a serial interface (for example COM1). But this seems to be very CPU intensive and if the user moves the wind

相关标签:
4条回答
  • 2021-02-02 05:06

    The classic solution is to have a FIFO buffer. Ensure that the size of the FIFO is large enough to handle any critical case where there is a lot of input and the processor block is being taken up.

    You could even have a 2-buffer system:

    --->|Reader|-->FIFO-->|Processor|--->FIFO2--->|Displayer|
    
    0 讨论(0)
  • 2021-02-02 05:07

    You should rewrite port_DataReceived procedure to read data until port.BytesToRead is greater then zero, like this:

    private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
            var port = (SerialPort)sender;
            while (port.BytesToRead > 0)
            {
                int byte_count = port.BytesToRead;
                byte[] buffer = new byte[byte_count];
    
                int read_count = port.Read(buffer, 0, byte_count);
    
                // PROCESS DATA HERE
    
            }
    }
    

    Also I would recommend you to just insert data in queue list in procedure port_DataReceived, and perform data processing in separate thread.

    0 讨论(0)
  • 2021-02-02 05:18

    I am surprised no one caught this. The SerialPort class utilizes its own thread when using the DataReceived event. This means that if the subscriber, for example, is accessing any Form elements, then it must be done so with either an Invoke, or BeginInvoke method(s). Otherwise, you end up with a cross thread operation. In older versions of .net, this would go along unnoticed with unpredictable behaviour (depending on the CPU cores in the PC) and in later versions, should raise an exception.

    0 讨论(0)
  • 2021-02-02 05:20

    Your last conclusion, that the event runs on the Main thread, may not be true for Windows App. Don't test this in a Console.

    The proper way to tune this is:

    • set a large enough buffer, although the minimum 4096 is usually Ok

    • set the ReceivedBytesThreshold as high as tolerable (and do it before the Open())

    • do as little as possible in the Received event, pass the data to a Queue or MemoryStream if you need more time

    0 讨论(0)
提交回复
热议问题