【问题标题】:C# Background Worker UI UpdateC# 后台工作者 UI 更新
【发布时间】:2011-09-28 08:26:41
【问题描述】:

我正在尝试使用后台工作程序从数据库中检索大量数据而不会停止主线程。这似乎运作良好,只是在更新 UI 时,更新会冻结屏幕。相关代码如下:

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {               
        lvwTest.BeginUpdate();
        lvwTest.Items.Clear();

        // Populate the UI
        foreach (TestItem ti in testData)
        {
            ListViewItem lvi = lvwTest.Items.Add(ti.Value1);
            lvi.SubItems.Add(ti.Value2);
        }

        lvwTest.EndUpdate();                     
    }

更新大约需要 2 到 3 秒,在此期间屏幕被锁定。我意识到只有主线程可以更新屏幕,但是是否可以以某种方式(在后台线程或列表视图的另一个实例中)将此数据加载到内存中,然后显示它?我只想让程序在不占用主线程时间的情况下简单地刷新数据。

【问题讨论】:

    标签: c# multithreading backgroundworker


    【解决方案1】:

    我建议将数据加载到内存中并使用 虚拟模式ListView。这样,您只需根据需要创建 ListViewItem 对象。

    【讨论】:

      【解决方案2】:

      如果您必须将大量数据加载到 UI 中,这将需要时间,并且会阻塞我们的应用程序。选项是智能滚动或分页。您加载所有数据,但根据用户请求逐个放置。

      【讨论】:

        【解决方案3】:

        由于以上大部分内容都是很好的建议,但并不能真正解决您当前的问题,因此这里有另一种方法: 这将更新您的 GUI 并保持响应。假设你在 WinForm App 中?

                Application.DoEvents();
                this.Refresh();
        

        尽管如此,这并不意味着你不应该听从上面的想法:-)

        【讨论】:

        • 它是一个 WinForm 应用程序 - 但在 VB6 时代,DoEvents 不受欢迎,因为它可以改变事件的顺序。在 C# 中不是这样吗?
        • 你可能是对的,从我所听到的情况来看,这仍然是一个小技巧。取决于您的应用程序的复杂性。我已经将我最后一个简单的应用程序重写为 WPF,这实际上是一个非常好的框架。
        【解决方案4】:

        除了虚拟化之外,我还建议将项目分成批次,例如 100 个,并将每个批次添加到自己的消息中。这样一来,在将批次添加到 ListView 时,UI 可以处理其他消息。

        换句话说,所有RunWorkerCompleted 处理程序所做的就是将第一批加入一个单独的消息中。然后添加方法将添加项目,然后将下一批排队。这将一直持续到没有更多项目要添加为止。此时,您将重新启用 UI 的相关部分(ListView)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-12-14
          • 1970-01-01
          • 2011-10-30
          • 2011-03-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多