Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将项添加到ListView控件时,UI冻结_C#_.net_Winforms - Fatal编程技术网

C# 将项添加到ListView控件时,UI冻结

C# 将项添加到ListView控件时,UI冻结,c#,.net,winforms,C#,.net,Winforms,我需要在加载东西时更新UI,我已经阅读并被告知,BackgroundWorker是Windows窗体桌面应用程序中用于此作业的正确“工具” 所以现在我想知道为什么当列表视图控件随着每个项目的添加而更新时,我的UI会冻结 private void Form1_Shown(object sender, EventArgs e) { if (library.Songs != null) { loader.Enabled = true; worker.Ru

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

所以现在我想知道为什么当
列表视图
控件
随着每个项目的添加而更新时,我的UI会冻结

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.
}

为什么我的用户界面冻结了?我如何阻止它?我以为使用BackgroundWorker的全部目的是为了在我们做事情的时候不让该死的UI冻结

更新:

我有一个理论认为这是因为加载了很多文件,因此对
ReportProgress(song)
的调用太多,因此UI更新被留在队列中等待进度调用完成

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

更新:

表格1.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();
            }
        }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Forms;
使用Microsoft.Xna.Framework.Media;
命名空间播放
{
公共部分类Form1:Form
{
公共媒体库=新媒体库();
公共静态列表歌曲=新列表();
公共表格1()
{
初始化组件();
}
公共void TestPlay()
{
list.BeginUpdate();
var itemsToAdd=library.Songs
.Select(x=>newlistViewItem(x.Artist.Name))
.ToArray();
list.Items.AddRange(itemsToAdd);
EndUpdate();
}
显示私有void Form1_(对象发送方,事件参数e)
{
TestPlay();
}
}
}

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

我建议您使用and
EndUpdate
方法,并在UI线程本身中填充列表。你可以完全抛弃那些没有任何价值的
BackgroundWorker

否则,创建需要添加的项的数组,然后调用
ListViewItems.AddRange
,该函数针对一次添加多个元素进行了优化

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

listView.Items.AddRange(itemsToAdd);

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

我建议您使用and
EndUpdate
方法,并在UI线程本身中填充列表。你可以完全抛弃那些没有任何价值的
BackgroundWorker

否则,创建需要添加的项的数组,然后调用
ListViewItems.AddRange
,该函数针对一次添加多个元素进行了优化

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

listView.Items.AddRange(itemsToAdd);

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

我建议您使用and
EndUpdate
方法,并在UI线程本身中填充列表。你可以完全抛弃那些没有任何价值的
BackgroundWorker

否则,创建需要添加的项的数组,然后调用
ListViewItems.AddRange
,该函数针对一次添加多个元素进行了优化

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

listView.Items.AddRange(itemsToAdd);

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

我建议您使用and
EndUpdate
方法,并在UI线程本身中填充列表。你可以完全抛弃那些没有任何价值的
BackgroundWorker

否则,创建需要添加的项的数组,然后调用
ListViewItems.AddRange
,该函数针对一次添加多个元素进行了优化

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

listView.Items.AddRange(itemsToAdd);


什么是
歌曲
?只是收藏?如果是这样,您就不需要
后台工作人员
。这只会增加噪音。您只需循环
库.Songs
并将其添加到UI线程中即可。@SriramSakthivel
Songs
是一个
歌曲集合,所以是的,它只是一个集合。因此,即使有5000首歌曲,将它们添加到UI线程的ListView中也不会阻止该线程或冻结任何内容?你误解了。它仍然会“阻止线程”和“冻结GUI”。只是在
后台工作人员中做同样的事情根本没有帮助。在您的示例中,
BackgroundWorker
中没有真正的工作要做-
歌曲。在这种情况下,添加
实际上是一个NOP-您仍然在GUI线程上完成所有工作(在
worker\u ProgressChanged
)。5000不是一个大数字。应该尽快添加。使用或
AddRange
方法。这里最耗时的操作是什么?什么是
library.Songs
?如果这也是一个集合,那么通过
BackgroundWorker
@SriramSakthivel,你不会得到任何东西,实际上我不能这样做。我需要UI在歌曲被添加到列表时做出响应。我刚刚尝试了你的建议,在添加项目时整个应用程序都没有响应(没有BackgroundWorker)。什么是
歌曲
?只是收藏?如果是这样,您就不需要
后台工作人员
。这只会增加噪音。您只需循环
库.Songs
并将其添加到UI线程中即可。@SriramSakthivel
Songs
是一个
歌曲集合,所以是的,它只是一个集合。因此,即使有5000首歌曲,也会将它们添加到列表中