winforms 在保持UI响应的同时向ListBox添加许多项

monwx1rj  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(121)

我正在尝试更新一个包含大量数据的ListBox,以保持用户界面(UI)的响应性。
为此,我使用以下代码将数据收集到100个项目的批中,然后将这些批一次性插入到ListBox中,而不是逐个插入每个项目。代码不能按预期工作,只有在所有项都添加到ListBox之后,UI才会更新。

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);
    }
}
ars1skjm

ars1skjm1#

您不需要多线程方法来更新UI。您所需要的只是在批量插入过程中通过使用ListBox.BeginUpdateListBox.EndUpdate方法暂停ListBox的绘制:

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

当您在弹性容器中动态加入控件,并且想要防止控件在加入每个新控件时跳来跳去时,就会使用Control.SuspendLayoutControl.ResumeLayout方法。

相关问题