0

If SerialPort_obj_DataReceived called by multi thread , in this case should I to use a lock or not ?

similar question here: serial port thread locking while processing data read from serial port

Thank you.

public partial class Ctwing : Form
    {

object myLock = new object();

       SerialPort serialPort_obj;

        List<byte> dataReceived;

        public Ctwing()
        {
            InitializeComponent();

            dataReceived = new List<byte>();

            serialPort_obj = new SerialPort();
            serialPort_obj.DataReceived += SerialPort_obj_DataReceived;
        }

        private void SerialPort_obj_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            byte[] buff = new byte[sp.BytesToRead];
            sp.Read(buff, 0, sp.BytesToRead);

            dataReceived.AddRange(buff);

/*  should I to use a lock or not ?
lock(myLock){
 dataReceived.AddRange(buff);
}
*/

        }

}

nothing. this is just a question.

2
  • Mind that starting with .Net 9, you are supposed to use the Lock class. Commented Jan 8 at 8:25
  • It depends on what you do with dataReceived and we don't know/see that. If dataReceived is considered some sort of queue for incoming data before its processed then maybe you just choose the wrong datatype for storing the incoming data. Something more fitting that would be also rather threadsafe by nature. Commented Jan 8 at 10:21

1 Answer 1

2

The documentation states:

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.

So the event is raised on a background thread. While the documentation is not as clear as I would like, it seem fairly safe to assume that the event cannot be called concurrently, and that there are memory barriers as appropriate. If this was not the case the event would be very difficult to use safely.

The question then becomes "is dataReceived accessed anywhere else?". If yes, then you need a lock, since accessing the same list from different threads require locking. You may also need some way to inform the UI thread that the list has changed, such as Control.BeginInvoke, or possibly just a timer.

I would also consider:

  1. Separating the UI from the serial port reader.
  2. Parsing the data into some kind of message structure in the reader.
Sign up to request clarification or add additional context in comments.

3 Comments

The documentation only mentions a secondary thread, which is not equal to the same secondary thread. It's actually invoked by the thread pool.
@shigo True. But do you disagree with the main point, i.e. that the event cannot be invoked concurrently? I tried to check the source, but I don't really understand how it is supposed to work.
You can only know that this event cannot not currently be invoked concurrently after reading the source code, but your answer came to this conclusion after referencing the documentation, which does not state this point, so this doesn't make sense.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.