Vahid
Vahid

Reputation: 5444

Add many items to ListBox while keeping the UI resposive

I am trying to update a ListBox with a large amount of data in a way that keeps the user interface (UI) responsive.

To do this, I am using the following code to collect the data into batches of 100 items, and then insert these batches into the ListBox in one go, rather than inserting each item individually. This should prevent the UI from being updated each time an item is added, but unfortunately, the code does not work as expected and the UI is only updated after all of the items have been added to the ListBox.

enter image description here

public partial class Form1 : Form
{
    private SynchronizationContext synchronizationContext;

    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        synchronizationContext = SynchronizationContext.Current;

        await Task.Run(() =>
        {
            ConcurrentDictionary<int, int> batch = new ConcurrentDictionary<int, int>();
            int count = 0;
            for (var i = 0; i <= 10000; i++)
            {
                batch[i] = i;
                count++;
                if (count == 100)
                {
                    count = 0;
                    UpdateUI(batch);
                    batch = new ConcurrentDictionary<int, int>();
                }

                
            }
        });
    }

    private void UpdateUI(ConcurrentDictionary<int, int> items)
    {
        synchronizationContext.Post(o =>
        {
            listBox1.SuspendLayout();
            foreach (var item in items)
            {
                listBox1.Items.Add(item.Value);
            }

            listBox1.ResumeLayout();

        }, null);
    }
}

Upvotes: 1

Views: 306

Answers (1)

Theodor Zoulias
Theodor Zoulias

Reputation: 43475

You don't need a multithreading approach in order to update the UI. All you need is to suspend the painting of the ListBox during the mass insert, by using the ListBox.BeginUpdate and ListBox.EndUpdate methods:

private void button1_Click(object sender, EventArgs e)
{
    listBox1.BeginUpdate();
    for (var i = 1; i <= 10000; i++)
    {
        listBox1.Items.Add(i);
    }
    listBox1.EndUpdate();
}

The Control.SuspendLayout and Control.ResumeLayout methods are used when you add controls dynamically in a flexible container, and you want to prevent the controls from jumping around when each new control is added.

Upvotes: 1

Related Questions