-2

I'm wondering what would be the best way to populate a ListBox control of a WinForm, populated depending on a radio btn?

I have seen some suggestions to use a foreach to loop over each object of my list, and Add() them to the listBox.items.Add(), but this seems to be a really bad idea, since the list from rabio btn 1 returns a list with 10.000 records (takes quiet some time to loop over, and the UI freeze while looping, bad bad idea).

Is there any better way to do this, and maybe in a seperated Task to stop UI freeze??

private void PopulateListBox()
{
    foreach (var item in Controller.ReturnBigResultSet())
            this.Invoke((MethodInvoker)(() => listBox1.Items.Add(item)));
}

UPDATE: Code block using AddRange:

var watch = new Stopwatch();
watch.Start();
var list = Controller.GetAllEntries().ToArray();
Debug.WriteLine("List returned in {0}s with a size of {1}", watch.Elapsed.TotalSeconds, list.Count<Lejlighed>());
watch.Restart();
listBox1.Items.AddRange(list);
watch.Stop();
Debug.WriteLine("Added {0} items in {1}s", listBox1.Items.Count, watch.Elapsed.TotalSeconds);

Output is:

List returned in 3.8596527s with a size of 19022
Added 19022 items in 1.9223412s
grmihel
  • 784
  • 3
  • 15
  • 40
  • 1
    You could send all 10,000 to a single invoke rather than invoking 10,000 times... use addrange instead of add. It's still going to take a lot of time though - just not designed to contain that many items - a LOT of code. – Shannon Holsinger Sep 05 '16 at 22:17
  • Does `listBox1.BeginUpdate()` before the loop and `listBox1.EndUpdate()` afterwards help at all? – Ry- Sep 05 '16 at 22:19
  • @Ryan Yes, it's equivalent to using `AddRange`. Also they don't need to call `Add` or `AddRange` from another thread. If they use `AddRange` or use `Add` with `BeginUpdate` and `EndUpdate`, populating is quick enough. – Reza Aghaei Sep 05 '16 at 22:46
  • Please don't edit the post, it makes the answer meaningless. – Reza Aghaei Sep 05 '16 at 23:15
  • @Reza Sorry, didn't have any other ways to posst the code, since code pasting in comments is badly formatted. Commented a followup in the answer. – grmihel Sep 05 '16 at 23:19

1 Answers1

3

You don't need to populate the ListBox from in another thread. If you use a correct way to populate it, populating 10000 items takes a short time (for me 200-300 ms).

The part that you may want to put in another thread is loading data not adding data to ListBox.

To add items to ListBox it's enough to use AddRange:

this.listBox1.AddRange(array);

Which is equivalent to using below code. First call BeginUpdate method of ListBox and then use a loop to Add items to Items collection and at last call EndUpdate:

this.listBox1.BeginUpdate();
foreach (var item in array)
{
    this.listBox1.Items.Add(item);
}
this.listBox1.EndUpdate();

Take a look at source code of AddRange method.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Oh, I just realized that the issue by using Items.AddRAnge is that my "list" is actually a generic IEnumrable and the AddRange requires a ObjectCollection. Any suggestions? – grmihel Sep 05 '16 at 22:52
  • Use `this.listBox1.Items.AddRange(list.ToArray());` – Reza Aghaei Sep 05 '16 at 23:02
  • Strange thing is, that I added a stopwatch on this, and it took 5.5s to load about 19000 entries :s Not really impressive. Could this really be true to take that long? – grmihel Sep 05 '16 at 23:06
  • Use it like I used, without Invoke. – Reza Aghaei Sep 05 '16 at 23:07
  • Updated the code with the blocks I use. Seems like it take some time to convert from IEnum to Array. – grmihel Sep 05 '16 at 23:14
  • Using above methods which I described you will have best performance. That's all I can share :) – Reza Aghaei Sep 05 '16 at 23:20
  • Seems better. Have to look on how to optimize the GetAllEntries part which is a data context, but thats another issue. At least your suggestion seems to improve the population quiet a bit. Thanks – grmihel Sep 05 '16 at 23:22
  • I would prefer to ask a new question about `AddRange` and `BeginUpdate-Add-EndUpdate` if the performance is unacceptable for me. Including the average result of executing those command at least 20-30 times. – Reza Aghaei Sep 05 '16 at 23:22