是否可以在后台线程中填充 ObjectListView?
Is it possible to populate an ObjectListView in a background thread?
我有一个应用程序向列表视图添加几千个项目。此操作可能需要一段时间,但这对应用程序来说很好。但是,我仍然希望在填充列表时有一个字幕进度条 运行,以便用户可以看到正在发生的事情。 进度条锁定,因为 UI 线程正忙于添加项目。
我尝试从后台工作程序填充列表视图控件,但进度条仍然锁定。这让我明白,由于列表控件存在于 UI 线程中,因此从后台工作者填充它实际上并没有改变任何东西。
有没有办法在这种情况下仍然有进度条运行?
我想知道是否可以在另一个线程中使用进度条 运行,但我不知道该怎么做,或者是否可行。
这是我的代码来说明(添加 2200 个对象):
List.SuspendLayout();
StatusText.Text = "Populating the list...";
ProgressBar.Style = ProgressBarStyle.Marquee;
List.SetObjects(items);
List.ResumeLayout();
我也尝试使用 BeginUpdate()
和 EndUpdate()
方法,但没有明显效果(我假设它也暂停和恢复布局)。
感谢您在评论中给我的指示,我能够确定填充列表时的加载延迟:这不是由于列表控件本身。每当将项目添加到列表中时,都会按预期访问要显示在列中的属性。但是,其中一些属性需要从数据库和磁盘额外加载数据。
为了解决这个问题,我创建了一个单独的后台工作程序来初始化项目的内部数据缓存,然后再将它们添加到列表中。在此之后,实际显示列表最多只需要几秒钟。
举例说明:
private void PopulateList()
{
StatusText.Text = "Populating the list...";
// start the background worker
PopulateListWorker.RunWorkerAsync();
}
private void Worker_PopulateList_DoWork(object sender, DoWorkEventArgs e)
{
// run the data cache initialization
}
private void Worker_PopulateList_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
private void Worker_PopulateList_Completed(object sender, RunWorkerCompletedEventArgs e)
{
List.SuspendLayout();
List.SetObjects(items);
List.ResumeLayout();
progressBar.Value = 0;
StatusText.Text = "All done.";
}
我有一个应用程序向列表视图添加几千个项目。此操作可能需要一段时间,但这对应用程序来说很好。但是,我仍然希望在填充列表时有一个字幕进度条 运行,以便用户可以看到正在发生的事情。 进度条锁定,因为 UI 线程正忙于添加项目。
我尝试从后台工作程序填充列表视图控件,但进度条仍然锁定。这让我明白,由于列表控件存在于 UI 线程中,因此从后台工作者填充它实际上并没有改变任何东西。
有没有办法在这种情况下仍然有进度条运行?
我想知道是否可以在另一个线程中使用进度条 运行,但我不知道该怎么做,或者是否可行。
这是我的代码来说明(添加 2200 个对象):
List.SuspendLayout();
StatusText.Text = "Populating the list...";
ProgressBar.Style = ProgressBarStyle.Marquee;
List.SetObjects(items);
List.ResumeLayout();
我也尝试使用 BeginUpdate()
和 EndUpdate()
方法,但没有明显效果(我假设它也暂停和恢复布局)。
感谢您在评论中给我的指示,我能够确定填充列表时的加载延迟:这不是由于列表控件本身。每当将项目添加到列表中时,都会按预期访问要显示在列中的属性。但是,其中一些属性需要从数据库和磁盘额外加载数据。
为了解决这个问题,我创建了一个单独的后台工作程序来初始化项目的内部数据缓存,然后再将它们添加到列表中。在此之后,实际显示列表最多只需要几秒钟。
举例说明:
private void PopulateList()
{
StatusText.Text = "Populating the list...";
// start the background worker
PopulateListWorker.RunWorkerAsync();
}
private void Worker_PopulateList_DoWork(object sender, DoWorkEventArgs e)
{
// run the data cache initialization
}
private void Worker_PopulateList_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
private void Worker_PopulateList_Completed(object sender, RunWorkerCompletedEventArgs e)
{
List.SuspendLayout();
List.SetObjects(items);
List.ResumeLayout();
progressBar.Value = 0;
StatusText.Text = "All done.";
}