Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Updating UI/Dataset from serialport

Updating UI/Dataset from serialport

Scheduled Pinned Locked Moved C#
wpfwcfdesignxmlhelp
24 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TheTinSoldier
    wrote on last edited by
    #1

    This problem has to do with updating a control/dataset based on the DataRecevied event of the serial port. Now I know you are thinking cross threading (which it might be) but let me explain. I have a dataset in the main UI form that is databound to a number of controls. When I change the values of the dataset the bound controls update. This is fine, but when I update the values of the dataset via the DataReceived event the values DON'T update? To illlustrate the problem simply I have stripped down the code to it's most basic form. I hope someone can shed some light on the problem. public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // create a dataset and populate it with data UnitDataSet uds = new UnitDataSet(); uds.DIns.ReadXml("Data.xml"); // create a new comms instance and pass a ref to the dataset _comms = new Comms(uds); // create a label to bind too Label lblInputState = new Label(); panel1.Controls.Add(lblInputState); // databind the control to the state column lblInputState.DataBindings.Add("Text", uds.Tables["DIns"], "state"); } // used to test if the binding works and value changes as expected public void button1_Click(object sender, EventArgs e) { _comms.ChangeValue(); } } ============================================================ class Comms { SerialPort _sp; UnitDataSet _uds; public Comms(UnitDataSet uds) { _uds = uds; _sp = new SerialPort("COM7", 9600, Parity.None, 8, StopBits.One); _sp.DataReceived += new SerialDataReceivedEventHandler(_sp_DataReceived); _sp.Open(); } private void _sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { // run this method when the event fires ChangeValue(); } // if i call this from the main form button (see above ) the value changes but if it's called // by the above DataReceived event the value doesn't change!?! public void ChangeValue() { // simple toggle to change the value bool tmp = (bool)_uds.Tables["DIns"].Rows[0]["state"]; _uds.Tables["DIns"].Rows[0]["state"] = !tmp; } } V

    E 1 Reply Last reply
    0
    • T TheTinSoldier

      This problem has to do with updating a control/dataset based on the DataRecevied event of the serial port. Now I know you are thinking cross threading (which it might be) but let me explain. I have a dataset in the main UI form that is databound to a number of controls. When I change the values of the dataset the bound controls update. This is fine, but when I update the values of the dataset via the DataReceived event the values DON'T update? To illlustrate the problem simply I have stripped down the code to it's most basic form. I hope someone can shed some light on the problem. public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // create a dataset and populate it with data UnitDataSet uds = new UnitDataSet(); uds.DIns.ReadXml("Data.xml"); // create a new comms instance and pass a ref to the dataset _comms = new Comms(uds); // create a label to bind too Label lblInputState = new Label(); panel1.Controls.Add(lblInputState); // databind the control to the state column lblInputState.DataBindings.Add("Text", uds.Tables["DIns"], "state"); } // used to test if the binding works and value changes as expected public void button1_Click(object sender, EventArgs e) { _comms.ChangeValue(); } } ============================================================ class Comms { SerialPort _sp; UnitDataSet _uds; public Comms(UnitDataSet uds) { _uds = uds; _sp = new SerialPort("COM7", 9600, Parity.None, 8, StopBits.One); _sp.DataReceived += new SerialDataReceivedEventHandler(_sp_DataReceived); _sp.Open(); } private void _sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { // run this method when the event fires ChangeValue(); } // if i call this from the main form button (see above ) the value changes but if it's called // by the above DataReceived event the value doesn't change!?! public void ChangeValue() { // simple toggle to change the value bool tmp = (bool)_uds.Tables["DIns"].Rows[0]["state"]; _uds.Tables["DIns"].Rows[0]["state"] = !tmp; } } V

      E Offline
      E Offline
      Ed Poore
      wrote on last edited by
      #2

      If you enable the debugger to break on all CLR exceptions (Tools -> Exceptions -> Check the box) and run the form under debug mode if it's a one of the many cross-thread problems then the debugger should trap the exception. Try using in the DataReceived handler, this.Invoke(ChangeValue), which will be thread-safe.

      T 2 Replies Last reply
      0
      • E Ed Poore

        If you enable the debugger to break on all CLR exceptions (Tools -> Exceptions -> Check the box) and run the form under debug mode if it's a one of the many cross-thread problems then the debugger should trap the exception. Try using in the DataReceived handler, this.Invoke(ChangeValue), which will be thread-safe.

        T Offline
        T Offline
        TheTinSoldier
        wrote on last edited by
        #3

        Thanks for you comments Ed. I can't seem to find Tools -> Exceptions. I'm using Visual C# express? I'll try your invoke method now.

        1 Reply Last reply
        0
        • E Ed Poore

          If you enable the debugger to break on all CLR exceptions (Tools -> Exceptions -> Check the box) and run the form under debug mode if it's a one of the many cross-thread problems then the debugger should trap the exception. Try using in the DataReceived handler, this.Invoke(ChangeValue), which will be thread-safe.

          T Offline
          T Offline
          TheTinSoldier
          wrote on last edited by
          #4

          there is no this.invoke() ??!

          E 1 Reply Last reply
          0
          • T TheTinSoldier

            there is no this.invoke() ??!

            E Offline
            E Offline
            Ed Poore
            wrote on last edited by
            #5

            The Invoke method is a member of the Form data type, it's used to provide thread-safe updates of the form's controls / components.  If you're not using a form you might want to take a look at my article[^] :->, which will allow you to do the thread-safe invocation from anywhere. The Exceptions box is under Debug | Exceptions sorry, I don't know about the express edition but that's where it is in the Standard edition of VS.

            T 1 Reply Last reply
            0
            • E Ed Poore

              The Invoke method is a member of the Form data type, it's used to provide thread-safe updates of the form's controls / components.  If you're not using a form you might want to take a look at my article[^] :->, which will allow you to do the thread-safe invocation from anywhere. The Exceptions box is under Debug | Exceptions sorry, I don't know about the express edition but that's where it is in the Standard edition of VS.

              T Offline
              T Offline
              TheTinSoldier
              wrote on last edited by
              #6

              Thanks Ed! Actually I saw you article today when I was searching for help. You are right it's not a form. I scanned over your article but it seemed quite complex to me (I still haven't really got my head around delegates or generics) but I'm fast running out of options so I'm going to study it and hopefully I'll find the answer.

              E 1 Reply Last reply
              0
              • T TheTinSoldier

                Thanks Ed! Actually I saw you article today when I was searching for help. You are right it's not a form. I scanned over your article but it seemed quite complex to me (I still haven't really got my head around delegates or generics) but I'm fast running out of options so I'm going to study it and hopefully I'll find the answer.

                E Offline
                E Offline
                Ed Poore
                wrote on last edited by
                #7

                The article actually needs an update, which will make it simpler to use (removes generics).  I've got the changed code here[^]. Basically from inside your DataReceived handler all you need to do is call:

                InvocationHelper.Invoke(this.ChangeValue);

                All the delegate is is a pointer to a function (if you know C), if you don't it's basically a variable which stores information about a particular function or method, you can then pass this variable around as a normal variable, and you can also invoke the function the delegate points to as well. The helper routine basically just bubbles up through the class hiearchy to see if the class implements the interface ISynchronizewhatever, this just defines the Invoke method and means that the class can do things in a thread-safe manner. PS, generics are quite simple to understand and incredibly useful once you know how.

                T 1 Reply Last reply
                0
                • E Ed Poore

                  The article actually needs an update, which will make it simpler to use (removes generics).  I've got the changed code here[^]. Basically from inside your DataReceived handler all you need to do is call:

                  InvocationHelper.Invoke(this.ChangeValue);

                  All the delegate is is a pointer to a function (if you know C), if you don't it's basically a variable which stores information about a particular function or method, you can then pass this variable around as a normal variable, and you can also invoke the function the delegate points to as well. The helper routine basically just bubbles up through the class hiearchy to see if the class implements the interface ISynchronizewhatever, this just defines the Invoke method and means that the class can do things in a thread-safe manner. PS, generics are quite simple to understand and incredibly useful once you know how.

                  T Offline
                  T Offline
                  TheTinSoldier
                  wrote on last edited by
                  #8

                  Thanks again Ed! I've just arrived and work this morning and it's great to see your message. Well, although I'm new to generics, I am actually using them in my project already. I'm sure I'll use them more and more as they do seem well suited to many situations, I'm just getting to the 'once you know how part'. The word delegate makes me nervous, but I'll put it with the 'once you know how' and I'm sure I'll get the hang of it. Hey, your source has been blocked, could you zip it please? Thanks heaps, you've been great. Oh, I forgot to say that under the Debug -> Exceptions, are you refering to the 'thrown' check box or the 'user-handled' check box associated with the CLR Exceptions tree? -- modified at 15:05 Wednesday 14th February, 2007

                  E 1 Reply Last reply
                  0
                  • T TheTinSoldier

                    Thanks again Ed! I've just arrived and work this morning and it's great to see your message. Well, although I'm new to generics, I am actually using them in my project already. I'm sure I'll use them more and more as they do seem well suited to many situations, I'm just getting to the 'once you know how part'. The word delegate makes me nervous, but I'll put it with the 'once you know how' and I'm sure I'll get the hang of it. Hey, your source has been blocked, could you zip it please? Thanks heaps, you've been great. Oh, I forgot to say that under the Debug -> Exceptions, are you refering to the 'thrown' check box or the 'user-handled' check box associated with the CLR Exceptions tree? -- modified at 15:05 Wednesday 14th February, 2007

                    E Offline
                    E Offline
                    Ed Poore
                    wrote on last edited by
                    #9

                    Ok, zipped, same location[^] but .zip on the end, thanks for finding that out about the .cs extensions, never knew about that. Best way to think of delegates is to just treat them as variables, they're nothing more anyway. The checkbox is thrown, it helps a lot because the debugger will break when an exception is thrown rather than when it is not handled, e.g. if you've got a try / catch block normally it'd pass through and execute the catch, but with this it breaks on the exception inside the try allowing you to find the source of the problem.

                    T 1 Reply Last reply
                    0
                    • E Ed Poore

                      Ok, zipped, same location[^] but .zip on the end, thanks for finding that out about the .cs extensions, never knew about that. Best way to think of delegates is to just treat them as variables, they're nothing more anyway. The checkbox is thrown, it helps a lot because the debugger will break when an exception is thrown rather than when it is not handled, e.g. if you've got a try / catch block normally it'd pass through and execute the catch, but with this it breaks on the exception inside the try allowing you to find the source of the problem.

                      T Offline
                      T Offline
                      TheTinSoldier
                      wrote on last edited by
                      #10

                      Great info about the exception I'll give it a crack now, and check out your helper class. Super! :-D

                      E 1 Reply Last reply
                      0
                      • T TheTinSoldier

                        Great info about the exception I'll give it a crack now, and check out your helper class. Super! :-D

                        E Offline
                        E Offline
                        Ed Poore
                        wrote on last edited by
                        #11

                        Let me know if it's successful.

                        T 1 Reply Last reply
                        0
                        • E Ed Poore

                          Let me know if it's successful.

                          T Offline
                          T Offline
                          TheTinSoldier
                          wrote on last edited by
                          #12

                          I have an error when I compile. This is the code I updated: private void _sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { // run this method when the event fires InvocationHelper.Invoke(this.ChangeValue); } Argument '1': cannot convert from 'method group' to 'System.Delegate' P.S If you prefer to have a fiddle yourself I can send you the source. Thanks for being so helpful.

                          E 1 Reply Last reply
                          0
                          • T TheTinSoldier

                            I have an error when I compile. This is the code I updated: private void _sp_DataReceived(object sender, SerialDataReceivedEventArgs e) { // run this method when the event fires InvocationHelper.Invoke(this.ChangeValue); } Argument '1': cannot convert from 'method group' to 'System.Delegate' P.S If you prefer to have a fiddle yourself I can send you the source. Thanks for being so helpful.

                            E Offline
                            E Offline
                            Ed Poore
                            wrote on last edited by
                            #13

                            Oops, forgot the delegate bit :doh:

                            private delegate void ChangeValueDelegate();

                            private void _sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
                            {
                                // run this method when the event fires
                                InvocationHelper.Invoke(new ChangedValueDelegate(this.ChangeValue));
                            }

                            T 1 Reply Last reply
                            0
                            • E Ed Poore

                              Oops, forgot the delegate bit :doh:

                              private delegate void ChangeValueDelegate();

                              private void _sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
                              {
                                  // run this method when the event fires
                                  InvocationHelper.Invoke(new ChangedValueDelegate(this.ChangeValue));
                              }

                              T Offline
                              T Offline
                              TheTinSoldier
                              wrote on last edited by
                              #14

                              Dang, didn't work. Does the block: // Invoke delegate normally singleCastDelegate.DynamicInvoke(arguments); Mean that it's not cross threaded? Curiously though, after I use your class then click on the button to change the value (just to see if it still works) it doesn't update the value in the label anymore... P.S I had to put a check in your code as I was getting an error if (arguments != null) <- here { if (requiredParameters != arguments.Length) .... }

                              E 2 Replies Last reply
                              0
                              • T TheTinSoldier

                                Dang, didn't work. Does the block: // Invoke delegate normally singleCastDelegate.DynamicInvoke(arguments); Mean that it's not cross threaded? Curiously though, after I use your class then click on the button to change the value (just to see if it still works) it doesn't update the value in the label anymore... P.S I had to put a check in your code as I was getting an error if (arguments != null) <- here { if (requiredParameters != arguments.Length) .... }

                                E Offline
                                E Offline
                                Ed Poore
                                wrote on last edited by
                                #15

                                Yes it's not cross-threading, I had a proper look through your code and now understand exactly what you're trying to do. Did you change the code in the button's event handler?  That can stay the same, it's only the SerialPort stuff because of the way that Windows uses a seperate thread to read data internally. Re: error, you can actually scrap the first "wrapper" method completely, it's not needed at all (in fact I don't know why it's there at all), if it wasn't there then you wouldn't need your check because of the params declaration the arguments array would be zero length as opposed to null :doh:. Try setting a breakpoint on the line including the ChangeValue inside the DataReceived handler, if that's hit then all handlers are setup properly for the SerialPort, then try F11 (in standard edition anyway) to do Debug -> Step Into, the debugger should then jump to the ChangeValue routine.  Just step through the code and examine the variables to see if anything untoward is happening.

                                T 1 Reply Last reply
                                0
                                • T TheTinSoldier

                                  Dang, didn't work. Does the block: // Invoke delegate normally singleCastDelegate.DynamicInvoke(arguments); Mean that it's not cross threaded? Curiously though, after I use your class then click on the button to change the value (just to see if it still works) it doesn't update the value in the label anymore... P.S I had to put a check in your code as I was getting an error if (arguments != null) <- here { if (requiredParameters != arguments.Length) .... }

                                  E Offline
                                  E Offline
                                  Ed Poore
                                  wrote on last edited by
                                  #16

                                  Now I'm confused, I just created a simple program to duplicate what you're doing and got some really bizarre behaviour.  If running without the VS debugger attached it works fine, with the debugger attached it won't update the textbox, just as your experiencing. :~ If you're interested my code is here[^], all there is is a small dataset (one table, one column), a form which has a combo box for selecting the serial port, a button to open / close the port and a textbox which is bound to the dataset.  I didn't create a seperate class like you did but experienced the same problem. But it works fine without the debugger :suss:

                                  T 1 Reply Last reply
                                  0
                                  • E Ed Poore

                                    Yes it's not cross-threading, I had a proper look through your code and now understand exactly what you're trying to do. Did you change the code in the button's event handler?  That can stay the same, it's only the SerialPort stuff because of the way that Windows uses a seperate thread to read data internally. Re: error, you can actually scrap the first "wrapper" method completely, it's not needed at all (in fact I don't know why it's there at all), if it wasn't there then you wouldn't need your check because of the params declaration the arguments array would be zero length as opposed to null :doh:. Try setting a breakpoint on the line including the ChangeValue inside the DataReceived handler, if that's hit then all handlers are setup properly for the SerialPort, then try F11 (in standard edition anyway) to do Debug -> Step Into, the debugger should then jump to the ChangeValue routine.  Just step through the code and examine the variables to see if anything untoward is happening.

                                    T Offline
                                    T Offline
                                    TheTinSoldier
                                    wrote on last edited by
                                    #17

                                    - I didn't change the code in the buttons event handler. - I scrapped the wrapper method. - The handler is firing ok, and I've stepped through the ChangeValue method, it's doing what it should - that is, it's changing the value in the dataset. I know this because whether the DataReceived event handler or the button event calls ChangeValue the value changes and I can see it as I step though that it's been changed from the previous value. What's not updating is the Text property of the Label control that the Dataset is bound to. P.S If I trigger the ChangeValue method via the button first, the label updates fine. But if I trigger ChangeValue via your delegate method and then try the button the label doesn't update.

                                    E 1 Reply Last reply
                                    0
                                    • T TheTinSoldier

                                      - I didn't change the code in the buttons event handler. - I scrapped the wrapper method. - The handler is firing ok, and I've stepped through the ChangeValue method, it's doing what it should - that is, it's changing the value in the dataset. I know this because whether the DataReceived event handler or the button event calls ChangeValue the value changes and I can see it as I step though that it's been changed from the previous value. What's not updating is the Text property of the Label control that the Dataset is bound to. P.S If I trigger the ChangeValue method via the button first, the label updates fine. But if I trigger ChangeValue via your delegate method and then try the button the label doesn't update.

                                      E Offline
                                      E Offline
                                      Ed Poore
                                      wrote on last edited by
                                      #18

                                      How does it behave without the debugger attached (Ctrl+F5)

                                      1 Reply Last reply
                                      0
                                      • E Ed Poore

                                        Now I'm confused, I just created a simple program to duplicate what you're doing and got some really bizarre behaviour.  If running without the VS debugger attached it works fine, with the debugger attached it won't update the textbox, just as your experiencing. :~ If you're interested my code is here[^], all there is is a small dataset (one table, one column), a form which has a combo box for selecting the serial port, a button to open / close the port and a textbox which is bound to the dataset.  I didn't create a seperate class like you did but experienced the same problem. But it works fine without the debugger :suss:

                                        T Offline
                                        T Offline
                                        TheTinSoldier
                                        wrote on last edited by
                                        #19

                                        Holy Bible Batman you're right!!!! Arrgggh! I didn't test your code but just tried it on my own and it works... thanks to you and your tenacious approach. And not one delegate or generic in sight! My workmate says that if your over our neck of the woods sometime (NZ) we owe you a beer. Thanks very much Ed, you've been a real help on a prob that had me completely stumped. :cool:

                                        E 1 Reply Last reply
                                        0
                                        • T TheTinSoldier

                                          Holy Bible Batman you're right!!!! Arrgggh! I didn't test your code but just tried it on my own and it works... thanks to you and your tenacious approach. And not one delegate or generic in sight! My workmate says that if your over our neck of the woods sometime (NZ) we owe you a beer. Thanks very much Ed, you've been a real help on a prob that had me completely stumped. :cool:

                                          E Offline
                                          E Offline
                                          Ed Poore
                                          wrote on last edited by
                                          #20

                                          Hmm, might take you up on that offer if I ever go down that way.  Confused though, you're in the States (according to bio) and you work in New Zealand? If it is the States I should hopefully be going from the 19th of April to 7th May, but that'll be Houston (7 days), San Antonio (7 days) and New York (4) days.  But most of the time will be spent shooting I think, World Championships being the reason for the trip. Glad to have been of help.

                                          T 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups