user3244329
user3244329

Reputation: 1

C# multiple COM port synchronization

I am porting an existing app from Borland C++ to .NET. Application handles 4 COM Ports simultaneously, i need to synchronize them, so that whilst one port is receiving data, the other three would block until one reads all the data in the receive buffer.

Requirements are, that new version works exactly in the same way as the previous one, so i need to find a way how to synchronize those 4 ports.

P.S.

I have got 4 instances of SerialPort class.

Below is a handler for receiving data over the COM port.

    private void SerialPort_DataReceived( object sender, SerialDataReceivedEventArgs e )
    {
        SerialPort rThis = (SerialPort)sender;

        string existingData = rThis.ReadExisting();
        int NumReceived = existingData.Length;
        if (NumReceived > 0)
        {
            char[] ReceivedByte = existingData.ToCharArray();
            // if RX bytes cannot be processed
            if (!rThis.ProcessReceivedBytes(ReceivedByte, NumReceived))
            {
                rThis.ReportThreadError(ThreadId.TI_READ, 0x07FFFFF);
            }
        }                           
    }

Upvotes: 0

Views: 1058

Answers (1)

pid
pid

Reputation: 11607

Best thing is you have only one thread interacting with the ports, because this way you can't interact with the other ports while the thread is busy. This is exactly what you want, forget about multi-threading here.

Then, you should separate that low-level I/O thread from the GUI thread. So you'll end up with two threads that comunicate with one another over a well-defined API.

The low-level I/O thread requires a way of polling the serial ports without blocking, something like this:

while(polling) // GUI thread may interrupt polling on user request
{
    foreach(SerialPort port in serialports)
    {
        if(port.HasDataToRead) // this is the polling you really need
        {
            // read data from port and handle it accordingly
        }
    }

    // ... suspend thread now and then to prevent loop from consuming CPU time
}

The HasDataToRead should be implemented in the event handler, meaning:

  • catch in the event handler the event data is available and signal it with HasDataToRead inside the SerialPort class;
  • don't read the actual data in the event handler, event handlers often run on the GUI thread, you don't want to lock up the GUI;
  • at the end of the read method clear the HasDataToRead flag.

The cycle above really is a dispatcher, while the events are only used to orchestrate the flags inside the SerialPort instances.

Pay attention to the HasDataToRead flag, you'll have to lock it to avoid race conditions:

lock(HasDataToRead)
{
    // access HasDataToRead
}

Upvotes: 0

Related Questions