Multiple objects containing SerialPort with same SerialDataReceivedEventHandler

1.1k views Asked by At

I have two objects (of the same class) which each contain a SerialPort object. The class has a method which handles the SerialPort.DataReceived event and is used by both SerialPort objects.

When I instantiate each object in a separate application, each port handles its DataReceived event individually as expected.

When I instantiate two instances of the COM_Front_End class in the same application and send data from one serial port to the other, both port's DataReceived event handlers fire. For short, I'll call this "cross-talk".

My class structure looks something like this:

public class COM_Front_End
{
    private SerialPort_custom port;
    private LockObject;

    public COM_Front_End(string PortName, string BaudRate)
    {
        // Other code

        port = new SerialPort_custom(PortName, BaudRate, new SerialDataReceivedEventHandler(SerialDataReceived));

        port.Open();
    }

    private void SerialDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        //lock (LockObject)  // A lock is not needed here. Only one SerialDataReceived event can fire at a time
        //{
            SerialPort port;

            try
            {
                port = sender as SerialPort;

                if (port != null)
                {
                    byte[] buffer = new byte[port.BytesToRead];
                    int bytesRead = port.Read(buffer, 0, buffer.Length);

                    foreach (byte inByte in buffer)
                    {
                        // Byte processing code
                    }
                }
            }
            catch (Exception ex)
            {
                // Exception handling code
            }
        //}
    }
}

The class containing the actual SerialPort class looks like:

public class SerialPort_custom : SerialPort
{
    public SerialPort_custom(string PortName, int BaudRate, SerialDataReceivedEventHandler DataReceivedHandler)
    {
        this.PortName = PortName;
        this.BaudRate = BaudRate;
        this.Parity = System.IO.Ports.Parity.None;
        this.DataBits = 8;
        this.StopBits = System.IO.Ports.StopBits.One;
        this.Handshake = System.IO.Ports.Handshake.None;
        this.RtsEnable = true;
        this.DtrEnable = true;
        this.DiscardNull = false;
        this.Encoding = Encoding.ASCII;

        this.DataReceived += DataReceivedHandler;
    }

    // Other methods
}

I have two instances of the COM_Front_End class in the same application. Whenever one instance receives data, both objects' SerialDataReceived methods fire.

Why does the DataReceived event handler fire for both serial ports when they are instantiated in the same application? Furthermore, how can I ensure that multiple instantiation of this class does not cause "cross-talk"?

1

There are 1 answers

0
Kashif On BEST ANSWER

I've found the root cause of my problem:

The project in which the COM_Front_End resides has two static classes. One of these classes is the Receive Buffer and the other the Transmit Buffer. Changing these classes so that they are not static solved my problem. Within each COM_Front_End object is a task which polls the Receive Buffer. Since they both use the same static class, they both were pulling from this buffer which explains why

A. The SerialDataReceived for both objects fired.

B. The data received for each was mangled/partial.

TL;DR: Non-static objects containing static objects will yield shared resources whether it is intended or not.

Please correct me wherever my explanation is faulty or incomplete.