加载DataTable缓慢当绑定到DataGridView.Datasource [英] Loading DataTable Slow When Bound to DataGridView.Datasource

查看:2099
本文介绍了加载DataTable缓慢当绑定到DataGridView.Datasource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经搜索过,我无法想象这一个。我正在处理一个Winforms UI,它正在拉大量的行,我需要在DataGridView中显示。我已经阅读了所有关于限制行数和分页,我绝对没有办法做到这一点。基本上我正在处理我在Codeplex上编写的SQL Server 2008扩展事件管理器的TargetDataViewer控件。



http://extendedeventmanager.codeplex.com/



我受限于我可以根据具体目标及其呈现数据。我想要做的是将从目标读取的数据流传输到DataGridView中,类似于Profiler或SQL Server Management Studio在数据流中显示数据的方式。我重写了大量代码,并将BackgroundWorker提取数据并将其处理为DataTable。如果我没有设置DataGridView.DataSource = DataTable,我可以在几分钟内将数据加载到数据表中,它的运行速度很快。一旦将DataTable添加到DataSource,它就会慢一点儿停止(而不是几分钟,同样的300K行可能需要1/2小时)。



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

解决方案

想想当您填入未绑定的 DataTable DataReader 中的一行:$ DataRow 创建,从 DataReader ,并添加到集合。然后,当您创建绑定时, DataGridView 从表中拉取数据,并在屏幕上构建视图。



当您填充 DataTable 时,会发生什么情况,其绑定到 DataGridView 已启用?一整堆事件处理。每次更改绑定属性时,属性更改的事件将被提升,绑定控件处理它。这不是30万次,每个发生30万次。



如果您关闭此功能,并且只会偶尔更新绑定的控件,该怎么办?看看这个方法:

  private void PopulateDataTable()
{
int rowCount = 10000;

bindingSource1.RaiseListChangedEvents = false; (int i = 0; i< rowCount; i ++)
{
DataRow r = DT.NewRow();
(int j = 0; j< ColumnCount; j ++)
{
r [j] =列+(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毫秒。



当然,如果我填充了30万行表,我不会每500行重置绑定;我可能会在500行标记上执行一次,然后将其关闭,直到操作完成。但是即使这样做,您需要经常调用 Application.DoEvents ,以便UI可以响应事件。



编辑



没关系 Application.DoEvents 如果您在后台任务中填充表,则不需要这样做。



但是,您需要确保重新设置绑定 BackgroundWorker ProgressChanged 事件处理程序,而不在 DoWork 方法。如果您在填充数据时确实允许用户在绑定的 DataGridView 中编辑数据,那么您将遇到一个受伤的世界。来源于另一个线程。


I've searched all over and I can't figure this one out. I am working on a Winforms UI that is pulling large volumes of rows that I need to display in a DataGridView. I have already read all about limiting row counts and paging and there is absolutely no good way for me to do this. Basically I am working on the TargetDataViewer control of the Extended Events Manager for SQL Server 2008 that I wrote on Codeplex.

http://extendedeventmanager.codeplex.com/

I am limited to what I can do based on the specific target and how it presents data. What I am trying to do is stream the data that has been read from a target into the DataGridView similar to how Profiler, or SQL Server Management Studio display data as it streams in. I rewrote a lot of code, and have a BackgroundWorker pulling data and processing it into a DataTable. If I don't set the DataGridView.DataSource = DataTable, I can load 300K+ rows of data into the DataTable in a few minutes, it really runs fast. As soon as I add the DataTable to the DataSource it slow to almost a halt (instead of a few minutes the same 300K rows can take a 1/2 hr).

I know that the problem isn't my processing code, it is specific to being bound to the DataGridView.DataSource, and I have timing code to prove this. I can't figure out how to get around this. For Performance I can late bind the control to the DataTable after the data is loaded, but that is a really crappy user experience. I see lots of people complaining about the DataGridView performance impact when loading data so this may just be a limitation I am stuck with? Any ideas?

解决方案

Think about what happens when you populate an unbound DataTable with one row from a DataReader: A DataRow gets created, populated from the DataReader, and added to the Rows collection. Then, when you create the binding, the DataGridView pulls data from the table and builds the view on the screen.

What happens when you populate a DataTable whose binding to the DataGridView is enabled? A whole mess of event handling. Every time you change a bound property, the property-changed event gets raised and the bound control handles it. That's not happening 300,000 times, it's happening 300,000 times for each column.

What if you turn this off, and only update the bound control occasionally? Look at this method:

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
}

You have to call ResetBindings to force the update of the bound control. This takes time, because you can't get around the cost of building the DataGridViewRow objects, but taking out the events is a significant improvement. On my machine, if I populate a 10-column, 10000 row DataTable that's bound to a DataGridView, it takes 2900 milliseconds. If I leave data-binding turned off the entire time, it takes 155 milliseconds. If I reset the bindings every 500 rows, it takes 840 milliseconds.

Of course, if I were populating 300,000 row table, I wouldn't reset the bindings every 500 rows; I'd probably do it once at the 500-row mark and then turn it off until the operation completes. But even if you do this, you need to call Application.DoEvents every so often, so that the UI can respond to events.

Edit

Never mind that bit about Application.DoEvents; you don't need to do that if you're populating the table in a background task.

But you do need to make sure that you're resetting the bindings in the BackgroundWorker's ProgressChanged event handler, and not in the DoWork method. And you're going to experience a world of hurt if you actually let the user edit data in the bound DataGridView while you're populating its data source on another thread.

这篇关于加载DataTable缓慢当绑定到DataGridView.Datasource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆