当项被添加到listviewcontrol时,UI冻结

本文关键字:UI 冻结 listviewcontrol 添加 | 更新日期: 2023-09-27 18:17:31

我需要更新UI 我正在加载的东西,我已经阅读并被告知,BackgroundWorker是正确的"工具"在Windows窗体桌面应用程序的工作。

所以现在我想知道为什么我的UI冻结而ListView Control更新,因为每个项目都添加到它。

private void Form1_Shown(object sender, EventArgs e)
{
    if (library.Songs != null)
    {
        loader.Enabled = true;
        worker.RunWorkerAsync();
    }
}
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
    int songCount = 0;
    foreach (Song song in library.Songs)
    {
        songs.Add(song);
        worker.ReportProgress(songCount++);
    }
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    list.Items.Add(songs[e.ProgressPercentage].Artist.Name);
    list.Update(); // This line is not the culprit. Removing it has no affect on the freezing.
    loader.Enabled = false;
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Hooray.
}

为什么我的UI冻结了,我该如何阻止它?我认为使用BackgroundWorker的全部意义就在于,当我们在做事情时,该死的UI不会冻结?!

更新:

我有一个理论,这正在发生,因为有许多文件正在加载,因此有太多的调用ReportProgress(song)发生,所以UI更新被留在队列中等待进度调用完成。

那么,如果是这样的话,我怎么才能把它分开,让它一次处理一定比例的歌曲呢?

更新:

Form1.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Microsoft.Xna.Framework.Media;
    namespace Play
    {
        public partial class Form1 : Form
        {
            public MediaLibrary library = new MediaLibrary();
            public static List<Song> songs = new List<Song>();
            public Form1()
            {
                InitializeComponent();
            }
            public void TestPlay()
            {
                list.BeginUpdate();
                var itemsToAdd = library.Songs
                            .Select(x => new ListViewItem(x.Artist.Name))
                            .ToArray();
                list.Items.AddRange(itemsToAdd);
                list.EndUpdate();
            }
            private void Form1_Shown(object sender, EventArgs e)
            {
                TestPlay();
            }
        }
}

当项被添加到listviewcontrol时,UI冻结

使用BackgroundWorker不会给您带来太多好处(在这种情况下)。它只是将Song添加到集合中,并要求UI线程将歌曲添加到ListView中。

我建议你使用ListView。BeginUpdate和EndUpdate方法,并在UI线程本身填充列表。你可以完全扔掉没有任何价值的BackgroundWorker

否则创建一个数组的项目,你需要添加,然后调用ListViewItems.AddRange优化一次添加多个元素。

var itemsToAdd = library.Songs
                        .Select(x => new ListViewItem(x.Artist.Name))
                        .ToArray();
listView.Items.AddRange(itemsToAdd);