我需要在我正在加载内容时更新UI ,并且我已经阅读并被告知BackgroundWorker
是Windows窗体中作业的正确“工具”桌面应用。
所以现在我想知道为什么我的用户界面会在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.
}
为什么我的用户界面会冻结,如何阻止它?我认为使用BackgroundWorker的重点在于,当我们正在做的事情时,血腥的UI不会冻结?!
更新
我有一个理论认为这种情况正在发生,因为有很多文件被加载,因此发生了ReportProgress(song)
的调用过多,因此UI更新被留在队列中等待Progress调用光洁度。
那么,如果是这样的话,我怎么能把它全部分开,以便它一次处理一定比例的歌曲呢?
更新
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();
}
}
}
答案 0 :(得分:3)
您的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);
已针对一次添加多个元素进行了优化。
{{1}}