System.IO.Ports.SerialPort and multithreading

I have SerialPort code that constantly needs to read data from a serial interface (e.g. COM1). But this is apparently very intense for the processor, and if the user moves the window or a large amount of data is displayed in the window (for example, bytes received on a serial line), the connection becomes messy.

Given the following code:

void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{

byte[] buffer = new byte[port.ReadBufferSize];

var count = 0;

try
{
    count = port.Read(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
    Console.Write(ex.ToString());
}

if (count == 0)
    return;

//Pass the data to the IDataCollector, if response != null an entire frame has been received


var response = collector.Collect(buffer.GetSubByteArray(0, count));

if (response != null)
{
    this.OnDataReceived(response);
}

The code needs to be collected since the data stream is constant and the data must be analyzed for (frames / packets).

    port = new SerialPort();

    //Port configuration code here...

    this.collector = dataCollector;

    //Event handlers
    port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
    port.Open();

If there is no user interaction in the window and nothing is added to the window, this works fine, but as soon as the interaction occurs, the communication is really messed up. Timeouts occur, etc.

For example, this will ruin everything:

Dispatcher.BeginInvoke(new Action(() =>
{
  var builder = new StringBuilder();
  foreach (var r in data)
  {
      builder.AppendFormat("0x{0:X} ", r);
  }


  builder.Append("\n\n");

  txtHexDump.AppendText(builder.ToString());

  txtHexDump.ScrollToEnd();


}),System.Windows.Threading.DispatcherPriority.ContextIdle);
});

But even simple log4net calls cause problems.

- SerialPort - , ...

Update:

, . ( ) :

class Program
{
    static void Main(string[] args)
    {
        var server = new BackgroundWorker();
        server.DoWork += new DoWorkEventHandler(server_DoWork);
        server.RunWorkerAsync();

        var port = new SerialPort();
        port.PortName = "COM2";
        port.Open();
        string input = "";

        Console.WriteLine("Client on COM2: {0}", Thread.CurrentThread.ManagedThreadId);
        while (input != "/quit")
        {
            input = Console.ReadLine();
            if (input != "/quit")
            {
                var data = ASCIIEncoding.ASCII.GetBytes(input);
                port.Write(data, 0, data.Length);
            }
        }

        port.Close();
        port.Dispose();
    }

    static void server_DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Listening on COM1: {0}", Thread.CurrentThread.ManagedThreadId);
        var port = new SerialPort();
        port.PortName = "COM1";
        port.Open();

        port.ReceivedBytesThreshold = 15;
        port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
    }

    static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var port = (SerialPort)sender;
        int count = 0;
        byte[] buffer = new byte[port.ReadBufferSize];
        count = ((SerialPort)sender).Read(buffer, 0, buffer.Length);

        string echo = ASCIIEncoding.ASCII.GetString(buffer,0,count);
        Console.WriteLine("-->{1} {0}", echo, Thread.CurrentThread.ManagedThreadId);
    }
}

:

COM1: 6 COM2: 10 , --- > 6 ,

, ....

, ?

+3
4

, , Windows App. .

:

  • , 4096 Ok

  • ReceivedBytesThreshold ( Open())

  • , MemoryStream,

+4

, . SerialPort DataReceived. , , , , , Invoke BeginInvoke. . .net ( ) , .

+11

port_DataReceived , port.BytesToRead , :

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

        }
}

port_DataReceived .

+2

The classic solution is to have a FIFO buffer. Make sure that the FIFO size is large enough to handle any critical case when there is a lot of input and the processor unit is being processed.

You may even have a 2-buffer system:

--->|Reader|-->FIFO-->|Processor|--->FIFO2--->|Displayer|
+1
source

Source: https://habr.com/ru/post/1710121/


All Articles