2

我有一个 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 线程上执行冗长的操作有关,并且我可能应该使用后台工作人员来完成这项工作。

有谁知道如何使用后台工作者的好和简单的例子。到目前为止,我发现的东西对我来说太复杂或太复杂了。

谢谢

克鲁兹

4

4 回答 4

1

如果你只想更新你的标签,你应该更新它。

labelLoadedLeft.Text = "Loading " + count + " files so far";
labelLoadedLeft.Update();

您使用哪个版本的 VS/C#?使用 VS2012/C#5.0,您可以利用新的“等待”功能。它使代码易于阅读,无需调用等即可更新 UI

于 2012-11-26T15:44:20.837 回答
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一次返回一个文件。

于 2012-11-26T15:49:40.013 回答
1

假设您使用的是 .NET 4.0,后台工作人员最容易通过TPL处理。您可以使用如下代码在后台启动工作人员:

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在你的程序中隐式地设置了一个状态机,所以除非你需要这样的功能,否则使用这个习惯用法可能会非常浪费。

于 2012-11-26T15:49:41.817 回答
0

你可能不需要它。在 ListView 上使用 Begin/EndUpdate。

http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.beginupdate.aspx

这将阻止绘制项目,直到它们全部加载。你将无法保持计数,但我根本看不到这样做的好处,特别是如果这让它太快而无关紧要。

于 2012-11-26T15:45:26.663 回答