1

I'm using in .

I simplified my app so that it just has a ListBox and a Button.

Here is my button click event:

private void button1_Click(object sender, EventArgs e)
{
    for (long i = 0; i < 66000; i++)
    {
        listBox1.Items.Add(i.ToString());
        listBox1.SelectedIndex = listBox1.Items.Count - 1;
    }
}

When I run my app and push the button I see the ListBox updating and after a while (it varies entry 3041 or so) the program will appear to hang as it adds the rest of the entries once its done, the ListBox will appropriately refresh.

Why the hang? Is it just too much to handle? I looked at my cpu usage and memory didn't seem to be using that much so I'm not sure what the problem is.

Abhishek
  • 2,925
  • 4
  • 34
  • 59
hrh
  • 658
  • 1
  • 14
  • 24
  • 1
    Why would you even at 66.000 items to listbox ? – Svexo May 20 '13 at 17:01
  • I don't actually need that many was using it to test a problem I was having in a bigger application I choose 66,000 because I seen in a different question that vista has problems when more then 65535 items are in a list, either way my problem happens way before it gets to that many items. – hrh May 20 '13 at 17:03
  • 1
    Yeah you've overwhelmed it. ListBoxes really don't like you doing that. If you really do need to add a load of items to a ListBox, either use [`ListBox.Items.AddRange()`](http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.objectcollection.addrange.aspx) or call [`ListBox.BeginUpdate()`](http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.beginupdate.aspx) before adding the items and [`ListBox.EndUpdate()`](http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.endupdate.aspx) afterwards. – Matthew Watson May 20 '13 at 17:11
  • @MatthewWatson Ill see if I can make any of those work, in my larger app its slightly more complicated then adding a bunch of lines at once but they do get added quite frequently as tasks complete. – hrh May 20 '13 at 17:17

2 Answers2

2

Every time you add an item, the memory it takes gets bigger, and since the items are in a dynamic list, the program may have to reallocate space.

Add to that the fact that you're probably using just one thread in that app (you're not using a background worker thread to update the list, right?) and you see why your app hangs. Windows forms always take a while when they have to update their controls... It's just that for normal, everyday use, they take milisseconds to update. For arcane uses like a list containing more than a few hundreds of items in the GUI, they'll take seconds or minutes to refresh, and you'll perceive that as hanging. Place the item handling in another thread, and you'll see that the form will update it's GUI pretty fast, but will take a long time between updates.

Geeky Guy
  • 9,229
  • 4
  • 42
  • 62
  • Wouldn't I see the memory getting used up in the Resource Monitor then? It didn't appear to be getting used up. – hrh May 20 '13 at 17:05
  • If you deallocate 10 mb and allocate 10mb and 1 byte, you won't see much change in the monitor. – Geeky Guy May 20 '13 at 17:06
  • 1
    Can u update with a backgroundworker though is it thread safe ? – Svexo May 20 '13 at 17:07
  • yea I can probably do that, in my actual app im only adding one item at at time as different tasks finish throughout my app. – hrh May 20 '13 at 17:08
  • 1
    I can't say it's thread safe. When the docs say something is thread safe in .NET, what they really mean is that it takes extra effort to mess things up. If they don't say anything about thread safety (which is the case with Listbox.Items), then it means handle with care. You'll probably have only two threads in a case like this, though, so it should be simple. – Geeky Guy May 20 '13 at 17:09
2

You misinterpret what's going on. Your listbox will freeze after 5 seconds. That's when Windows steps in when it notices that you are not taking care of the normal duties of a UI thread. Your window is replaced by the so-called "ghost window" to tell the user you've gone catatonic and that doing things like clicking the Close button isn't going to have any effect.

The easiest way to tell that you got the ghost window is from its title bar, it says "Not Responding".

A version of it that will fare somewhat better:

    private void button1_Click(object sender, EventArgs e) {
        listBox1.BeginUpdate();
        for (long i = 0; i < 66000; i++) {
            listBox1.Items.Add(i.ToString());
        }
        listBox1.EndUpdate();
        listBox1.SelectedIndex = listBox1.Items.Count - 1;
    }

You shouldn't otherwise expect windows to behave reasonable when you do unreasonable things. And you shouldn't expect users to behave reasonable either when they are faced with this UI disaster. But they'll let you know themselves.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thanks, the for loop was just a test case of what I was experiencing in my larger application, in my larger app its slightly more complicated then adding a bunch of lines at once but they do get added quite frequently as tasks complete, I will however try out Begin and End Update. =) – hrh May 20 '13 at 18:47