none
SerialPort SerialDataReceivedEventHandler Question RRS feed

  • General discussion

  • I can't fully grasp  SerialPort SerialDataReceivedEventHandler. I have these codes, how can I pass the serial port value that I read to a textbox with event handler.? Thanks

                                                        

    [code]

    this.serialPort1.DataReceived += new SerialDataReceivedEventHandler(p_DataReceived); // Add DataReceived Event Handler

    [/code]

                                                        

    [code]

      //read sms
            private void button3_Click(object sender, EventArgs e)
            {

                if (this.serialPort1.IsOpen)
                {

                  serialPort1.BaseStream.Flush();




                  string a = "sm"; string b = "all";
                  //this.serialPort1.Write("AT+CPMS=\"" + a + "\"\r\n");
                // this.serialPort1.Write("AT+CPMS=SM\r\n");

                     // this.serialPort1.Write("AT+CMGF=1\r\n");
                     //this.serialPort1.Write("AT+CSCS=\"PCCP437\"");
                     //this.serialPort1.Write("AT+CPMS=\"" + a + "\"\r\n");
                     this.serialPort1.Write("AT+CMGR=2\r");



                  //this.serialPort1.Write("AT+CMGL=\"" + b + "\"\r\n");

              MessageBox.Show("\nMessage Was Read\n", "Information");


                }

               else
               {
                    MessageBox.Show("\nSerial Port Is Not Open\n", " ERROR ");
               }


            }

    [/code]

    [code]

    public void p_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                //string s = (sender as SerialPort).ReadExisting();
                //buff += s;
                //textBox5.Text = "aa";
            }

    [/code]

    Wednesday, September 5, 2012 10:07 AM

All replies

  • The handler for the DataReceived event runs on a thread  pool thread. From that thread, you are not allowed to call methods on the UI thread such as textBox5.text - except for the four thread safe methods Invoke, BeginInvoke, EndInvoke and CreateGraphics. In practice this means that you have two possibilities:

    1) You can "wake" a method on the UI thread by means of the MethodInvoker delegate and an Invoke call, when the handler for the DataReceived event is executed, and then call the receive methods from the method you "wake".

    2) You can receive in the handler for the DataReceived event, and then make a delegate, which makes it possible to marshal the data to a method on the UI thread in a BeginInvoke or Invoke call.

    It is a very long storry. If you don't mind VB examples, you can find all the information you need in my SerialPort tutorial. Read especially the chapter: "SerialPort Receive".


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.

    Wednesday, September 5, 2012 10:52 AM
  • I did this below it now show the serial port data on the text box. What way did I use? Did what I do, a good way to read serial port data? 


    this.serialPort1.DataReceived += new SerialDataReceivedEventHandler(p_DataReceived); // Add DataReceived Event Handler
      private void DisplayText(object sender, EventArgs e)
            {
                textBox5.AppendText(RxString);
            }
    
            public void p_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                RxString = serialPort1.ReadExisting();
                this.Invoke(new EventHandler(DisplayText));
            }
    
    
    



    • Edited by jambyvedar Thursday, September 6, 2012 6:58 AM
    Thursday, September 6, 2012 2:09 AM
  • Your code is a combination of the two methods. The way you just "wake" DisplayText without transferring any data in a delegate is method 1. However, you receive in the handler for the DataReceived event, and this is method 2. It is perfectly OK to do it that way, but I have two comments:

    Since you don't use the information about the instance that raises the event, it is better to use the standard delegate MethodInvoker instead of EventHandler (see method 1). Because it has no data to transfer, it is able to cut some corners internal in .Net and in this way speed up things.

    Since you use Invoke, you need to close the port from a different thread as explained in chapter "SerialPort Receive" of my tutorial. You have no such code (have you not read the chapter?). Note that because you use a common buffer, you cannot just change Invoke to BeginInvoke without a risk of overwriting your buffer.


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.

    Thursday, September 6, 2012 7:01 AM
  • Hi, I read some parts of your tutorial. So after reading some tutorials, I tried this(code below), is this the standard delegate Method Invoker you are talking about?I am wondering why is that if I don't put  Thread.Sleep(500) on serial data receive event, sometimes it does not display the data on listview sometimes it will display it but not all the data(listview)? Listview is also put on Displaytext method;

    this.serialPort1.DataReceived += new SerialDataReceivedEventHandler(p_DataReceived); // Add DataReceived Event Handler  

     private delegate void SetTextDeleg(string text);

      private void DisplayText(string RxString)
            {

                textBox5.AppendText(RxString);         }         public void p_DataReceived(object sender, SerialDataReceivedEventArgs e)         {             RxString = serialPort1.ReadExisting();             //this.Invoke(new EventHandler(DisplayText));

     this.BeginInvoke(new SetTextDeleg(DisplayText), new object[] { RxString });         }

    I also encounter this code while reading some tutorial. What is the idea behind it? Why is that the delegate instance is inside a method, and you will call that same method?

    private void WriteToRichEdit ( string p )
    {
       if (richTextBox1.InvokeRequired)
          richTextBox1.Invoke(
    new RichEditWriteDelegate(WriteToRichEdit), new object[] { p });
       else
          richTextBox1.Text += p + "\n";
    }

    • Edited by jambyvedar Friday, September 7, 2012 6:20 AM
    Friday, September 7, 2012 3:50 AM
  • "... , is this the standard delegate Method Invoker you are talking about?"

    Do you see anything with the name MethodInvoker in your code?

    I wrote the tutorial because I was tired of answering the same questions again and again. Now you ask a question, which is answered in the chapter "Standard Delegates".

    "I am wondering why is that if I don't put Thread.Sleep(500) on serial data receive event, sometimes it does not display the data on listview sometimes it will display it but not all the data(listview)? "

    I don't see any sleep(500) in your code, so how can I answer that question? Note however that ReadExisting will only return what is present in the receive buffer at the time of the call and this is not necessary your full telegram. If you delay the call, it is more likely that it is, but it is bad programming to rely on a timer instead of making a protocol, which can tell exactly when the telegram is finished.

    "I also encounter this code while reading some tutorial. What is the idea behind it? Why is that the delegate instance is inside a method, and you will call that same method?"

    I don't know. Seems like a strange loop. In your case, it is not necessary to check for InvokeRequired - you know Invoke IS required.


    Everything should be made as simple as possible, but not simpler. Any fool can write code that a computer can understand. Good programmers write code that humans understand.


    Friday, September 7, 2012 8:24 AM