绑定到 DataGridView.Datasource 时加载 DataTable 缓慢

2023-12-12

我搜遍了所有地方,但我无法弄清楚这一点。我正在开发一个 Winforms UI,该 UI 正在提取需要在 DataGridView 中显示的大量行。我已经阅读了有关限制行数和分页的所有内容,但我绝对没有好的方法可以做到这一点。基本上,我正在研究我在 Codeplex 上编写的 SQL Server 2008 扩展事件管理器的 TargetDataViewer 控件。

http://extendedeventmanager.codeplex.com/

我只能根据具体目标及其呈现数据的方式来做什么。我想要做的是将已从目标读取的数据流式传输到 DataGridView 中,类似于 Profiler 或 SQL Server Management Studio 在流式传输时显示数据的方式。我重写了很多代码,并让 BackgroundWorker 提取数据并将其处理成数据表。如果我不设置DataGridView.DataSource = DataTable,我可以在几分钟内将300K+行数据加载到DataTable中,它确实运行得很快。一旦我将 DataTable 添加到 DataSource,它就会慢到几乎停止(而不是几分钟,相同的 300K 行可能需要 1/2 小时)。

我知道问题不是我的处理代码,它特定于绑定到 DataGridView.DataSource,并且我有计时代码来证明这一点。我不知道如何解决这个问题。为了性能,我可以在加载数据后将控件绑定到 DataTable,但这确实是一个糟糕的用户体验。我看到很多人抱怨加载数据时 DataGridView 的性能影响,所以这可能只是我遇到的限制?有任何想法吗?


考虑一下当你填充一个未绑定的对象时会发生什么DataTable与 a 中的一行DataReader: A DataRow被创建,填充自DataReader,并添加到Rows收藏。然后,当您创建绑定时,DataGridView从表中提取数据并在屏幕上构建视图。

当您填充一个时会发生什么DataTable其绑定到DataGridView已启用?一团糟的事件处理。每次更改绑定属性时,都会引发属性更改事件并由绑定控件处理该事件。这不是发生了 300,000 次,而是每个都发生了 300,000 次column.

如果您将其关闭并且仅偶尔更新绑定控件会怎么样?看看这个方法:

private void PopulateDataTable()
{
    int rowCount = 10000;

    bindingSource1.RaiseListChangedEvents = false;
    for (int i = 0; i < rowCount; i++)
    {
        DataRow r = DT.NewRow();
        for (int j = 0; j < ColumnCount; j++)
        {
            r[j] = "Column" + (j + 1);
        }
        DT.Rows.Add(r);

        if (i % 500 == 0)
        {
            bindingSource1.RaiseListChangedEvents = true;
            bindingSource1.ResetBindings(false);
            Application.DoEvents();
            bindingSource1.RaiseListChangedEvents = false;
        }
    }
    bindingSource1.RaiseListChangedEvents = true
}

您必须调用 ResetBindings 来强制更新绑定控件。这需要时间,因为你无法规避建造成本DataGridViewRow对象,但取出事件是一个重大改进。在我的机器上,如果我填充 10 列、10000 行DataTable这绑定到DataGridView,需要2900毫秒。如果我一直关闭数据绑定,则需要 155 毫秒。如果我每 500 行重置一次绑定,则需要 840 毫秒。

当然,如果我要填充 300,000 行表,我不会每 500 行重置一次绑定;我可能会在 500 行标记处执行一次,然后将其关闭,直到操作完成。但即使你这样做,你也需要打电话Application.DoEvents每隔一段时间,以便 UI 可以响应事件。

Edit

别介意那一点Application.DoEvents;如果您在后台任务中填充表,则不需要这样做。

但您确实需要确保重置中的绑定BackgroundWorker's ProgressChanged事件处理程序,而不是在DoWork方法。如果你真的让用户这么做,你将会经历一个充满伤害的世界edit绑定中的数据DataGridView当您在另一个线程上填充其数据源时。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

绑定到 DataGridView.Datasource 时加载 DataTable 缓慢 的相关文章

随机推荐