我有一个ListView,我填充了很多项目,超过3000.这可能需要15秒。 每次我添加一个项目,我想更新一个标签,说明到目前为止已添加了多少项目。 为此,我使用此代码:
foreach (FileInfo f in dir.GetFiles("*.*", SearchOption.AllDirectories))
{
DateTime dt = GetDateTakenFromImage(Path.Combine(f.Directory.ToString(), f.Name));
count++;
labelLoadedLeft.Text = "Loading " + count + " files so far";
ListViewItem lSingleItem = lv.Items.Add(f.Name);
lSingleItem.SubItems.Add(dt.ToString("dd MMMM yyyy"));
lSingleItem.Tag = Path.Combine(f.Directory.ToString(), f.Name);
}
不幸的是,在加载所有项目之前,标签不会显示。
我理解这与我在thr UI线程上进行冗长操作的事实有关,我应该使用后台工作来完成这项工作。
有没有人知道如何使用后台工作者的好的和简单的例子。到目前为止,我所发现的对我来说太复杂或太复杂。
谢谢
Crouz
答案 0 :(得分:1)
如果您只想更新标签,则应更新它。
labelLoadedLeft.Text = "Loading " + count + " files so far";
labelLoadedLeft.Update();
您使用的是哪个版本的VS / C#?使用VS2012 / C#5.0,您可以利用新的“等待”功能。它使代码易于阅读和更新UI可以在不调用等的情况下完成
答案 1 :(得分:1)
你可以使用BackgroundWorker来做,这是一个例子,http://dotnetforum.net/topic/34729-how-to-cancel-backgroundworker-during-getfiles/。
但是,在获得所有文件的列表之前,UI永远不会显示任何内容。正如你所说,这很慢。
使用EnumerateFiles
方法,http://msdn.microsoft.com/en-us/library/dd383458(v=vs.100).aspx,一次返回一个文件。
答案 2 :(得分:1)
后台工作人员最容易通过TPL处理,假设您正在使用.NET 4.0。您可以使用如下代码在后台启动工作人员:
Task.Factory.StartNew( () =>
{
// Background Worker Stuff goes here
}, TaskCreationOptions.LongRunning);
然后,您可以将您的工作人员的工作放在另一个班级/职能部门,并从yield return
获取DoWork()
结果,并为您提供IEnumerable<T>
所返回的任何内容。像这样使用foreach
循环:
foreach(var item in DoWork())
{
// Update UI
}
意味着您可以在结果返回时更新UI。 Yield return
将允许您在整个可枚举返回之前处理项目。但要小心 - yield return
隐式在程序中设置一个状态机,所以除非你需要这样的功能,否则使用这个习惯用法会非常浪费。
答案 3 :(得分:0)
您可能不需要它。在ListView上使用Begin / EndUpdate。
http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.beginupdate.aspx
这将阻止绘制项目,直到它们全部加载为止。你将无法维持一个计数,但我根本没有看到它的好处,特别是如果这使得它太快而无关紧要。