向 ListBox 添加许多项目,同时保持 UI 响应
Posted
技术标签:
【中文标题】向 ListBox 添加许多项目,同时保持 UI 响应【英文标题】:Add many items to ListBox while keeping the UI resposive 【发布时间】:2021-07-21 20:00:41 【问题描述】:我正在尝试使用大量数据更新 ListBox 并同时保持 UI 响应。
这是我用来实现此目的的代码,遍历 10000 个项目,将它们收集到 100 个项目的批次中,然后一次性插入这 100 个项目,这样我就可以避免每次添加单个项目时更新 UI,但不幸的是,代码不起作用,只有在将所有 10000 个项目实际添加到 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);
【问题讨论】:
您可以用BeginInvoke()
替换整个 SynchronizationContext 和 Post() 方法调用(因为所有方法都在同一个 Form 类中工作。否则,传递一个 Progress<T> 委托:这是一个简化的方法将 Post() 发送到 SynchronizationContext 而不显式捕获它,IProgress<T>
委托会为您执行此操作)。那么,你不需要SuspendLayout()
/ResumeLayout()
(无关),而是BeginUpdate()
/EndUpdate()
。
也许这会有所帮助:***.com/questions/2341731/…
a) AddRange b) 如果你关心 UI,为什么要添加这么多项目??
【参考方案1】:
您不需要多线程方法来更新 UI。您只需使用ListBox.BeginUpdate
和ListBox.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.SuspendLayout
和 Control.ResumeLayout
方法用于在灵活容器中动态添加控件,并且希望在添加每个新控件时防止控件跳来跳去。
【讨论】:
那么只需:listBox1.DataSource = Enumerable.Range(0, 10000).Select(i => i).ToArray();
。 -- 确实,OP 没有指定是否调用阻塞方法来获取此项目集合,但可能是这种情况。不过,OP 应该澄清,数据源很重要以上是关于向 ListBox 添加许多项目,同时保持 UI 响应的主要内容,如果未能解决你的问题,请参考以下文章
C# WPF 如何在向 Stackpanel 添加许多 UI 元素时保持应用程序响应
WPF:如何在调整大小后保持 ListBox SelectedItem 可见?
是否有在保持颜色的同时向 ggplot 饼图添加模式的功能?