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. Windows Forms
  4. ListBox does not update when DataSource is changed

ListBox does not update when DataSource is changed

Scheduled Pinned Locked Moved Windows Forms
helpquestionannouncement
23 Posts 5 Posters 8 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.
  • R rbsbscrp

    Well, I'm plum out of ideas. I've got a listbox with a List<> for its DataSource. When I init it - before the form is displayed, it works. But not after that. I am modifying the List<> contents and then I run:

    public void RefreshLbx()
    {
    lbxQuotes.DataSource = null;
    lbxQuotes.DataSource = _quotes;
    }

    where _quotes is the List<> Now here is where it gets weird. I put a button on the form - here's its handler:

    private void btnRefresh_Click(object sender, EventArgs e)
    {
    RefreshLbx();
    }

    So that when I click on the button then the lbxQuotes listbox is properly updated. But in the modification code - where I call RefreshLbx() directly, nothing happens. I even tried invoking btnRefresh_Click() in the code, but alas could not find the magic. Oh one other thought - the modification code is in a timer event handler - could this be a problem of trying to modify a control from a different thread? All I am doing is changing the List<> contents and then reseting the DataSource. I must be missing something to kick the listbox to redisplay, or something... HELP!

    C Offline
    C Offline
    Chirag Baroliya R
    wrote on last edited by
    #3

    Try This : public partial class Form1 : Form { public Form1() { InitializeComponent(); List<KeyValuePair<int, string>> data = new List<KeyValuePair<int, string>>(); KeyValuePair<int, string> item; for (int i = 1; i < 10; i++) { item = new KeyValuePair<int, string>(i, "Item " + i.ToString()); data.Add(item); } listBox1.DataSource = data; listBox1.DisplayMember = "Value"; listBox1.ValueMember = "Key"; } private void button1_Click(object sender, EventArgs e) { KeyValuePair<int, string> item = new KeyValuePair<int,string>(11,"Item 11"); List<KeyValuePair<int, string>> data = (List<KeyValuePair<int, string>>)listBox1.DataSource; data.Add(item); listBox1.DataSource = null; listBox1.DataSource = data; } }

    R 1 Reply Last reply
    0
    • R rbsbscrp

      Wow but this is weird. Okay, I found the solution because I tried the recommendation given below:

      lbxQuotes.DataSource = null;
      lbxQuotes.DataSource = _quotes;
      lbxQuotes.SelectionMode = SelectionMode.None;
      lbxQuotes.SelectionMode = SelectionMode.One;

      That is, I added the SelectionMode two lines... and this caused (only once) a "from different thread" exception. Weird, I'm NOT running a method - I'm changing data... hmmm... I wonder if the DataSource is instead a Property (which secretly runs a method). D'oh! Okay, so the solution was to create a delegate in the main form, for the RefreshLbx method, and have the RefreshLbx method recursively call this, as below:

      public void RefreshLbx()
      {
      if (lbxQuotes.InvokeRequired)
      {
      lbxQuotes.Invoke(_refreshLbx);
      }
      else
      {
      lbxQuotes.DataSource = null;
      lbxQuotes.DataSource = _quotes;
      }
      }

      with the _refreshLbx delegate defined in the form's class as:

      private delegate void RefreshLbxDg8();
      private RefreshLbxDg8 _refreshLbx;

      Then just init the delegate in the form constructor (after the InitializeComponent() call):

          \_refreshLbx = RefreshLbx;
      

      Now I am able to update the listbox contents from a timer handler.

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #4

      "System.Threading.Timer" is not threadsafe. You didn't use the Timer from the Toolbox, did you?

      rbsbscrp wrote:

      Weird, I'm NOT running a method - I'm changing data... hmmm...

      You're changing a property from a different thread than where the control was created.

      rbsbscrp wrote:

      if the DataSource is instead a Property (which secretly runs a method).

      Yup, it's a property; meaning it's built from two methods (not threads!)

      Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

      1 Reply Last reply
      0
      • R rbsbscrp

        Wow but this is weird. Okay, I found the solution because I tried the recommendation given below:

        lbxQuotes.DataSource = null;
        lbxQuotes.DataSource = _quotes;
        lbxQuotes.SelectionMode = SelectionMode.None;
        lbxQuotes.SelectionMode = SelectionMode.One;

        That is, I added the SelectionMode two lines... and this caused (only once) a "from different thread" exception. Weird, I'm NOT running a method - I'm changing data... hmmm... I wonder if the DataSource is instead a Property (which secretly runs a method). D'oh! Okay, so the solution was to create a delegate in the main form, for the RefreshLbx method, and have the RefreshLbx method recursively call this, as below:

        public void RefreshLbx()
        {
        if (lbxQuotes.InvokeRequired)
        {
        lbxQuotes.Invoke(_refreshLbx);
        }
        else
        {
        lbxQuotes.DataSource = null;
        lbxQuotes.DataSource = _quotes;
        }
        }

        with the _refreshLbx delegate defined in the form's class as:

        private delegate void RefreshLbxDg8();
        private RefreshLbxDg8 _refreshLbx;

        Then just init the delegate in the form constructor (after the InitializeComponent() call):

            \_refreshLbx = RefreshLbx;
        

        Now I am able to update the listbox contents from a timer handler.

        D Offline
        D Offline
        Dave Kreskowiak
        wrote on last edited by
        #5

        You can NOT so much as touch ANY part of a control from a thread other than the one that created it, the UI (or startup) thread. This is where your entire problem comes from. You have to Invoke methods on the UI thread that manipulates the control for your calling code.

        A guide to posting questions on CodeProject[^]
        Dave Kreskowiak

        R 1 Reply Last reply
        0
        • D Dave Kreskowiak

          You can NOT so much as touch ANY part of a control from a thread other than the one that created it, the UI (or startup) thread. This is where your entire problem comes from. You have to Invoke methods on the UI thread that manipulates the control for your calling code.

          A guide to posting questions on CodeProject[^]
          Dave Kreskowiak

          R Offline
          R Offline
          rbsbscrp
          wrote on last edited by
          #6

          My thanks to all who responded. >>

          You can NOT so much as touch ANY part of a control from a thread other than the one that created it, the UI (or startup) thread. This is where your entire problem comes from.

          My confusion was mostly that I was not trying to run a Method at all - I was just changing a Property (or what I thought was DATA). Upon more consideration, I realized that a Property is just syntactic sugar over a procedure call, anyway, so the "you can't run code from a different thread" rule applied even changing a Property. However, I am mystified as to WHY this rule "no touchie from different thread" even exists. Sure, if I'm trying to update a TextBox from other threads then there *could* be confusion and a random mix of characters added from the various threads due to the asynchronous timing of the code in the different threads. Yes, there *could* be... it is *possible* - just like I could really mess up a data structure if I update it from many threads without synchronization. But that is exactly what multithreaded coding is all about - synchronizing the use of common data structures (at least it is a major issue, if not the biggest issue). But why would the compiler assume that I am needing multithreading synchronization when updating a Textbox? The truth is, I am doing something at timed intervals - I am using a timer. It just so *happens* that C# chooses internally to implement a timer via a separate new thread. That is not *my* problem. I'm not trying to append text to the textbox from 17 different timers or asynchronous threads. I'm simply trying to update a textbox at constant intervals - in this case the system chooses to do this via ONE (other) thread. Suddenly now I have to become fully knowledgeable about multithreading and delegates and "invoking", etc. BAH! Unnecessary, unneeded, unwanted complexification. Aside from all that, I especially did not appreciate that the code simply failed to do anything - I got no compiler warning/error nor any runtime problem. My dialogbox simply didn't update. Then I had the fire up The Google and go searching for why it didn't work. My first real clue was that if I caused the update to happen from the very same function, via a click of a button on the UI, then it worked. Whaaa? My code definitely worked, but only if executed via a pushbutton. I've coded for years, and I'm teaching myself C# now, and "yeah" this is a noobie kinda problem, but geeeez what an unnecessary timewaster. Okay, 'nuff whining. Thx to all who re

          L D 2 Replies Last reply
          0
          • C Chirag Baroliya R

            Try This : public partial class Form1 : Form { public Form1() { InitializeComponent(); List<KeyValuePair<int, string>> data = new List<KeyValuePair<int, string>>(); KeyValuePair<int, string> item; for (int i = 1; i < 10; i++) { item = new KeyValuePair<int, string>(i, "Item " + i.ToString()); data.Add(item); } listBox1.DataSource = data; listBox1.DisplayMember = "Value"; listBox1.ValueMember = "Key"; } private void button1_Click(object sender, EventArgs e) { KeyValuePair<int, string> item = new KeyValuePair<int,string>(11,"Item 11"); List<KeyValuePair<int, string>> data = (List<KeyValuePair<int, string>>)listBox1.DataSource; data.Add(item); listBox1.DataSource = null; listBox1.DataSource = data; } }

            R Offline
            R Offline
            rbsbscrp
            wrote on last edited by
            #7

            Kuel. I like that you can use a List<> of Key/Values for a ListBox. Did not know that. Then can use the DataMember, ValueMember flexibility. Thx. However... You are executing the update from a button_click Method - thus the code is executed on the UI thread - thus it will work. My problem is that I am executing from a timer handler - because I need the update at regular intervals (taking samples) - thus the handler is on a different thread and thus, when executed, silently does absolutely nothing. Thx for the code. Educational. (and 'yes' I got it working)

            1 Reply Last reply
            0
            • R rbsbscrp

              My thanks to all who responded. >>

              You can NOT so much as touch ANY part of a control from a thread other than the one that created it, the UI (or startup) thread. This is where your entire problem comes from.

              My confusion was mostly that I was not trying to run a Method at all - I was just changing a Property (or what I thought was DATA). Upon more consideration, I realized that a Property is just syntactic sugar over a procedure call, anyway, so the "you can't run code from a different thread" rule applied even changing a Property. However, I am mystified as to WHY this rule "no touchie from different thread" even exists. Sure, if I'm trying to update a TextBox from other threads then there *could* be confusion and a random mix of characters added from the various threads due to the asynchronous timing of the code in the different threads. Yes, there *could* be... it is *possible* - just like I could really mess up a data structure if I update it from many threads without synchronization. But that is exactly what multithreaded coding is all about - synchronizing the use of common data structures (at least it is a major issue, if not the biggest issue). But why would the compiler assume that I am needing multithreading synchronization when updating a Textbox? The truth is, I am doing something at timed intervals - I am using a timer. It just so *happens* that C# chooses internally to implement a timer via a separate new thread. That is not *my* problem. I'm not trying to append text to the textbox from 17 different timers or asynchronous threads. I'm simply trying to update a textbox at constant intervals - in this case the system chooses to do this via ONE (other) thread. Suddenly now I have to become fully knowledgeable about multithreading and delegates and "invoking", etc. BAH! Unnecessary, unneeded, unwanted complexification. Aside from all that, I especially did not appreciate that the code simply failed to do anything - I got no compiler warning/error nor any runtime problem. My dialogbox simply didn't update. Then I had the fire up The Google and go searching for why it didn't work. My first real clue was that if I caused the update to happen from the very same function, via a click of a button on the UI, then it worked. Whaaa? My code definitely worked, but only if executed via a pushbutton. I've coded for years, and I'm teaching myself C# now, and "yeah" this is a noobie kinda problem, but geeeez what an unnecessary timewaster. Okay, 'nuff whining. Thx to all who re

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #8

              rbsbscrp wrote:

              It just so *happens* that C# chooses internally to implement a timer via a separate new thread.

              The timer from the toolbox doesn't; it's simply a component that raises an event at a specified interval.

              rbsbscrp wrote:

              That is not *my* problem.

              True - you're simply using the wrong timer-control. (Yes, there's more than one)

              rbsbscrp wrote:

              I found some code example for doing a "invoke" via a deleagate, etc., etc., and got it working.

              :thumbsup:

              Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

              1 Reply Last reply
              0
              • R rbsbscrp

                My thanks to all who responded. >>

                You can NOT so much as touch ANY part of a control from a thread other than the one that created it, the UI (or startup) thread. This is where your entire problem comes from.

                My confusion was mostly that I was not trying to run a Method at all - I was just changing a Property (or what I thought was DATA). Upon more consideration, I realized that a Property is just syntactic sugar over a procedure call, anyway, so the "you can't run code from a different thread" rule applied even changing a Property. However, I am mystified as to WHY this rule "no touchie from different thread" even exists. Sure, if I'm trying to update a TextBox from other threads then there *could* be confusion and a random mix of characters added from the various threads due to the asynchronous timing of the code in the different threads. Yes, there *could* be... it is *possible* - just like I could really mess up a data structure if I update it from many threads without synchronization. But that is exactly what multithreaded coding is all about - synchronizing the use of common data structures (at least it is a major issue, if not the biggest issue). But why would the compiler assume that I am needing multithreading synchronization when updating a Textbox? The truth is, I am doing something at timed intervals - I am using a timer. It just so *happens* that C# chooses internally to implement a timer via a separate new thread. That is not *my* problem. I'm not trying to append text to the textbox from 17 different timers or asynchronous threads. I'm simply trying to update a textbox at constant intervals - in this case the system chooses to do this via ONE (other) thread. Suddenly now I have to become fully knowledgeable about multithreading and delegates and "invoking", etc. BAH! Unnecessary, unneeded, unwanted complexification. Aside from all that, I especially did not appreciate that the code simply failed to do anything - I got no compiler warning/error nor any runtime problem. My dialogbox simply didn't update. Then I had the fire up The Google and go searching for why it didn't work. My first real clue was that if I caused the update to happen from the very same function, via a click of a button on the UI, then it worked. Whaaa? My code definitely worked, but only if executed via a pushbutton. I've coded for years, and I'm teaching myself C# now, and "yeah" this is a noobie kinda problem, but geeeez what an unnecessary timewaster. Okay, 'nuff whining. Thx to all who re

                D Offline
                D Offline
                Dave Kreskowiak
                wrote on last edited by
                #9

                Wow! You have such a myopic view of what's going on. The reason you need Invoke is because controls are NOT thread safe. What you see in the toolbox are .NET wrappers around standard window variants you find in Win32. They are not thread safe because of limitations in the Windows user interface. The golden rule is that any operation on a control is required to be done by the thread that created the window handle. It's possible to wrap all this code in synchronzation code, but that would have been a ton of code and a rather large performance hit. But, but, but "I'm just changing a property!" Yeah, I know. A property is nothing but a method that gets/sets a value, but that method can also do other things like validation, modifying other values inside the control, updating the controls internal state machine, kicking off events, and whatever else the controls need. What you're forgetting is that Windows is a shared system. Not only can your code cause code in the contorl to run, but Windows can too, AT ANY TIME. It can send your control a WM_PAINT message to get your control to repaint itself, but, what if you were changing the Text or Forecolor properties, from your thread, at the exact same time the control was getting these values to use in the paint code?? Invoke is there because .NET, like any other application, has to follow the "UI thread rule" like any other application. A little tidbit: The only methods on controls that ARE thread safe are Invoke, BeginInvoke, EndInvoke and CreateGraphics.

                A guide to posting questions on CodeProject[^]
                Dave Kreskowiak

                R 1 Reply Last reply
                0
                • D Dave Kreskowiak

                  Wow! You have such a myopic view of what's going on. The reason you need Invoke is because controls are NOT thread safe. What you see in the toolbox are .NET wrappers around standard window variants you find in Win32. They are not thread safe because of limitations in the Windows user interface. The golden rule is that any operation on a control is required to be done by the thread that created the window handle. It's possible to wrap all this code in synchronzation code, but that would have been a ton of code and a rather large performance hit. But, but, but "I'm just changing a property!" Yeah, I know. A property is nothing but a method that gets/sets a value, but that method can also do other things like validation, modifying other values inside the control, updating the controls internal state machine, kicking off events, and whatever else the controls need. What you're forgetting is that Windows is a shared system. Not only can your code cause code in the contorl to run, but Windows can too, AT ANY TIME. It can send your control a WM_PAINT message to get your control to repaint itself, but, what if you were changing the Text or Forecolor properties, from your thread, at the exact same time the control was getting these values to use in the paint code?? Invoke is there because .NET, like any other application, has to follow the "UI thread rule" like any other application. A little tidbit: The only methods on controls that ARE thread safe are Invoke, BeginInvoke, EndInvoke and CreateGraphics.

                  A guide to posting questions on CodeProject[^]
                  Dave Kreskowiak

                  R Offline
                  R Offline
                  rbsbscrp
                  wrote on last edited by
                  #10

                  Wow! You have such a myopic view of what's going on.

                  I don't think so. Let's revisit this one more time. So I'm supposed to put all code that modifies a control into wrapper code that calls invoke and this wrapper code ends up being a conditional test to see if invoke is required and then recursively calling the same function thru a special delegate that is created just for that invoke call. I've repeated my example code below:

                  private delegate void RefreshLbxDg8();
                  private RefreshLbxDg8 _refreshLbx;
                  ...
                  _refreshLbx = RefreshLbx;
                  ...
                  public void RefreshLbx()
                  {
                  if (lbxQuotes.InvokeRequired)
                  {
                  lbxQuotes.Invoke(_refreshLbx);
                  }
                  else
                  {
                  lbxQuotes.DataSource = null;
                  lbxQuotes.DataSource = _quotes;
                  }
                  }

                  All this is required in order that the code gets executed on the GUI thread. Now, I'm simply updating a textbox with a sample (number). Nothing else. I guess I could have stated my point better: yes, it is an asynchronous system and it is *possible* that a WM_PAINT would get processed while the textbox text is changing. I am aware of this. My complaint was that .NET designers used this sledgehammer solution to prevent any presentation rendering mishap (ie. my number is rendered while it is changing) by constraining all code to execute on the GUI thread. So this means that for every single interaction with any control - and there's a LOT of them, I'm supposed to write wrapper code around everything, and this wrapper code involves defining and creating delegates and rewriting all my code to include a conditional statement which tests for this invokability. AND YOU'RE FINE WITH THIS. Me, I think this is a horrible and terribly primitive solution and design. It would be better to leave me with using SendMessage() to inject my action into the GUI's Message-Loop. And that's not to mention that the compiler gave no warnings, there was no runtime error, the code SILENTLY failed, and I had no idea that the timer implemented its actions with a (hidden) separate thread. I am LESS than impressed.

                  D L 2 Replies Last reply
                  0
                  • R rbsbscrp

                    Wow! You have such a myopic view of what's going on.

                    I don't think so. Let's revisit this one more time. So I'm supposed to put all code that modifies a control into wrapper code that calls invoke and this wrapper code ends up being a conditional test to see if invoke is required and then recursively calling the same function thru a special delegate that is created just for that invoke call. I've repeated my example code below:

                    private delegate void RefreshLbxDg8();
                    private RefreshLbxDg8 _refreshLbx;
                    ...
                    _refreshLbx = RefreshLbx;
                    ...
                    public void RefreshLbx()
                    {
                    if (lbxQuotes.InvokeRequired)
                    {
                    lbxQuotes.Invoke(_refreshLbx);
                    }
                    else
                    {
                    lbxQuotes.DataSource = null;
                    lbxQuotes.DataSource = _quotes;
                    }
                    }

                    All this is required in order that the code gets executed on the GUI thread. Now, I'm simply updating a textbox with a sample (number). Nothing else. I guess I could have stated my point better: yes, it is an asynchronous system and it is *possible* that a WM_PAINT would get processed while the textbox text is changing. I am aware of this. My complaint was that .NET designers used this sledgehammer solution to prevent any presentation rendering mishap (ie. my number is rendered while it is changing) by constraining all code to execute on the GUI thread. So this means that for every single interaction with any control - and there's a LOT of them, I'm supposed to write wrapper code around everything, and this wrapper code involves defining and creating delegates and rewriting all my code to include a conditional statement which tests for this invokability. AND YOU'RE FINE WITH THIS. Me, I think this is a horrible and terribly primitive solution and design. It would be better to leave me with using SendMessage() to inject my action into the GUI's Message-Loop. And that's not to mention that the compiler gave no warnings, there was no runtime error, the code SILENTLY failed, and I had no idea that the timer implemented its actions with a (hidden) separate thread. I am LESS than impressed.

                    D Offline
                    D Offline
                    Dave Kreskowiak
                    wrote on last edited by
                    #11

                    Liek I said, it's a limitation in Windows Win32 since the dark arges, not .NET. If this bugs the crap out of you, go write code for Linux.

                    A guide to posting questions on CodeProject[^]
                    Dave Kreskowiak

                    R 1 Reply Last reply
                    0
                    • D Dave Kreskowiak

                      Liek I said, it's a limitation in Windows Win32 since the dark arges, not .NET. If this bugs the crap out of you, go write code for Linux.

                      A guide to posting questions on CodeProject[^]
                      Dave Kreskowiak

                      R Offline
                      R Offline
                      rbsbscrp
                      wrote on last edited by
                      #12

                      A SendMessage() call works between threads... at least I thought it did. Thus I thought this was a .NET constraint. If it's not a .NET new constraint then I just learned something.

                      Dave Kreskowiak wrote:

                      go write code for Linux.

                      No! (so there)

                      D 1 Reply Last reply
                      0
                      • R rbsbscrp

                        A SendMessage() call works between threads... at least I thought it did. Thus I thought this was a .NET constraint. If it's not a .NET new constraint then I just learned something.

                        Dave Kreskowiak wrote:

                        go write code for Linux.

                        No! (so there)

                        D Offline
                        D Offline
                        Dave Kreskowiak
                        wrote on last edited by
                        #13

                        rbsbscrp wrote:

                        No! (so there)

                        Then quit bitching...

                        A guide to posting questions on CodeProject[^]
                        Dave Kreskowiak

                        R 1 Reply Last reply
                        0
                        • D Dave Kreskowiak

                          rbsbscrp wrote:

                          No! (so there)

                          Then quit bitching...

                          A guide to posting questions on CodeProject[^]
                          Dave Kreskowiak

                          R Offline
                          R Offline
                          rbsbscrp
                          wrote on last edited by
                          #14

                          Dave Kreskowiak wrote:

                          Then quit bitching...

                          Your discourse is not civil, but constant.

                          L 1 Reply Last reply
                          0
                          • R rbsbscrp

                            Wow! You have such a myopic view of what's going on.

                            I don't think so. Let's revisit this one more time. So I'm supposed to put all code that modifies a control into wrapper code that calls invoke and this wrapper code ends up being a conditional test to see if invoke is required and then recursively calling the same function thru a special delegate that is created just for that invoke call. I've repeated my example code below:

                            private delegate void RefreshLbxDg8();
                            private RefreshLbxDg8 _refreshLbx;
                            ...
                            _refreshLbx = RefreshLbx;
                            ...
                            public void RefreshLbx()
                            {
                            if (lbxQuotes.InvokeRequired)
                            {
                            lbxQuotes.Invoke(_refreshLbx);
                            }
                            else
                            {
                            lbxQuotes.DataSource = null;
                            lbxQuotes.DataSource = _quotes;
                            }
                            }

                            All this is required in order that the code gets executed on the GUI thread. Now, I'm simply updating a textbox with a sample (number). Nothing else. I guess I could have stated my point better: yes, it is an asynchronous system and it is *possible* that a WM_PAINT would get processed while the textbox text is changing. I am aware of this. My complaint was that .NET designers used this sledgehammer solution to prevent any presentation rendering mishap (ie. my number is rendered while it is changing) by constraining all code to execute on the GUI thread. So this means that for every single interaction with any control - and there's a LOT of them, I'm supposed to write wrapper code around everything, and this wrapper code involves defining and creating delegates and rewriting all my code to include a conditional statement which tests for this invokability. AND YOU'RE FINE WITH THIS. Me, I think this is a horrible and terribly primitive solution and design. It would be better to leave me with using SendMessage() to inject my action into the GUI's Message-Loop. And that's not to mention that the compiler gave no warnings, there was no runtime error, the code SILENTLY failed, and I had no idea that the timer implemented its actions with a (hidden) separate thread. I am LESS than impressed.

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #15

                            rbsbscrp wrote:

                            Me, I think this is a horrible and terribly primitive solution and design.

                            Microsoft had the same idea; that's why the threaded version of the timer isn't in the WinForms designer-toolbox. The Timer from the toolbox simply raises events on the GUI-thread. No syncing required.

                            Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                            R 1 Reply Last reply
                            0
                            • R rbsbscrp

                              Dave Kreskowiak wrote:

                              Then quit bitching...

                              Your discourse is not civil, but constant.

                              L Offline
                              L Offline
                              Lost User
                              wrote on last edited by
                              #16

                              Let it go. It's like looking at a game who will have the last word on a subject. FWIW; Linux/Mono would react exactly the same.

                              1 Reply Last reply
                              0
                              • L Lost User

                                rbsbscrp wrote:

                                Me, I think this is a horrible and terribly primitive solution and design.

                                Microsoft had the same idea; that's why the threaded version of the timer isn't in the WinForms designer-toolbox. The Timer from the toolbox simply raises events on the GUI-thread. No syncing required.

                                Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                                R Offline
                                R Offline
                                rbsbscrp
                                wrote on last edited by
                                #17

                                Hmmmmm... I am using a System.Windows.Forms.Timer. Isn't that the one you are referring to that doesn't use a separate thread? Okay, now I'm confused. My code works if i execute it from a button. It works if I invoke it thru a delegate. Other than that nothing happens.

                                L 1 Reply Last reply
                                0
                                • R rbsbscrp

                                  Hmmmmm... I am using a System.Windows.Forms.Timer. Isn't that the one you are referring to that doesn't use a separate thread? Okay, now I'm confused. My code works if i execute it from a button. It works if I invoke it thru a delegate. Other than that nothing happens.

                                  L Offline
                                  L Offline
                                  Lost User
                                  wrote on last edited by
                                  #18

                                  Let me add to the confusion; there's not two, but three[^] timers available. So, which timer is it? :) ..and there's a picture in that article of a second timer in the toolbox. Nice to see my previous post invalidated that quickly.

                                  Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                                  R 1 Reply Last reply
                                  0
                                  • L Lost User

                                    Let me add to the confusion; there's not two, but three[^] timers available. So, which timer is it? :) ..and there's a picture in that article of a second timer in the toolbox. Nice to see my previous post invalidated that quickly.

                                    Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                                    R Offline
                                    R Offline
                                    rbsbscrp
                                    wrote on last edited by
                                    #19

                                    Wow, wonderful article. Again, the timer that I'm using is the System.Windows.Forms.Timer one (I'm cut&pasting this from the .Designer.cs file - and I don't see any other timers) Thx for the article. I'll look at all this in a bit.

                                    L 1 Reply Last reply
                                    0
                                    • R rbsbscrp

                                      Wow, wonderful article. Again, the timer that I'm using is the System.Windows.Forms.Timer one (I'm cut&pasting this from the .Designer.cs file - and I don't see any other timers) Thx for the article. I'll look at all this in a bit.

                                      L Offline
                                      L Offline
                                      Lost User
                                      wrote on last edited by
                                      #20

                                      rbsbscrp wrote:

                                      the timer that I'm using is the System.Windows.Forms.Timer one

                                      That one runs on the UI thread, and doesn't need any invocations to update controls created.

                                      using System;
                                      using System.Windows.Forms;
                                      using System.Threading;
                                      namespace WindowsFormsApplication1
                                      {
                                      public partial class Form1 : Form
                                      {
                                      public Form1()
                                      {
                                      InitializeComponent();
                                      Thread.CurrentThread.Name = "UI Thread";
                                      }

                                          private void timer1\_Tick(object sender, EventArgs e)
                                          {
                                              Text = String.Format("{0}, {1}", Thread.CurrentThread.Name, Environment.TickCount);
                                              // Thread.Sleep(1000); Try resizing after uncommenting this
                                          }
                                      }
                                      

                                      }

                                      The timer is based on the Windows message-pump;

                                      // System.Windows.Forms.Timer.TimerNativeWindow
                                      protected override void WndProc(ref Message m)
                                      {
                                      if (m.Msg == 275)
                                      {
                                      if ((int)m.WParam == this._timerID)
                                      {
                                      this._owner.OnTick(EventArgs.Empty);
                                      return;
                                      }
                                      }
                                      else
                                      {
                                      if (m.Msg == 16)
                                      {
                                      this.StopTimer(true, m.HWnd);
                                      return;
                                      }
                                      }
                                      base.WndProc(ref m);
                                      }

                                      Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^]

                                      1 Reply Last reply
                                      0
                                      • R rbsbscrp

                                        Wow but this is weird. Okay, I found the solution because I tried the recommendation given below:

                                        lbxQuotes.DataSource = null;
                                        lbxQuotes.DataSource = _quotes;
                                        lbxQuotes.SelectionMode = SelectionMode.None;
                                        lbxQuotes.SelectionMode = SelectionMode.One;

                                        That is, I added the SelectionMode two lines... and this caused (only once) a "from different thread" exception. Weird, I'm NOT running a method - I'm changing data... hmmm... I wonder if the DataSource is instead a Property (which secretly runs a method). D'oh! Okay, so the solution was to create a delegate in the main form, for the RefreshLbx method, and have the RefreshLbx method recursively call this, as below:

                                        public void RefreshLbx()
                                        {
                                        if (lbxQuotes.InvokeRequired)
                                        {
                                        lbxQuotes.Invoke(_refreshLbx);
                                        }
                                        else
                                        {
                                        lbxQuotes.DataSource = null;
                                        lbxQuotes.DataSource = _quotes;
                                        }
                                        }

                                        with the _refreshLbx delegate defined in the form's class as:

                                        private delegate void RefreshLbxDg8();
                                        private RefreshLbxDg8 _refreshLbx;

                                        Then just init the delegate in the form constructor (after the InitializeComponent() call):

                                            \_refreshLbx = RefreshLbx;
                                        

                                        Now I am able to update the listbox contents from a timer handler.

                                        T Offline
                                        T Offline
                                        TnTinMn
                                        wrote on last edited by
                                        #21

                                        I know that this is a bit late, but have you ever considered using the BindingList(Of T) Class[^] instead? It will notify any changes to the list so that the bound control can take action.

                                        R 1 Reply Last reply
                                        0
                                        • T TnTinMn

                                          I know that this is a bit late, but have you ever considered using the BindingList(Of T) Class[^] instead? It will notify any changes to the list so that the bound control can take action.

                                          R Offline
                                          R Offline
                                          rbsbscrp
                                          wrote on last edited by
                                          #22

                                          I'm not familiar with BindingList. I took a quick look at the link but am unsure of its benefit here. Thx for the heads up, though.

                                          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