【问题标题】:DataGridView performance in combination with a BindingList datasource结合 BindingList 数据源的 DataGridView 性能
【发布时间】:2012-05-08 16:25:02
【问题描述】:

我正在构建一个必须显示从外部系统接收到的数据的应用程序。这些数据可以很快进入,而每行占用的字节量相对较小。这意味着每个时间单位必须添加很多行。我目前的接收数据速度似乎比我能处理的要快,这意味着我的内存使用量正在上升。

我认为其中很大一部分与绘制实际的 dataGridView 有关。我对 dataGridView 做了一些小调整,希望它已经可以提高性能。 (例如禁用自动大小、特殊样式等)

在最近的一次添加中,我添加了行的着色,这是必需的。目前我的应用程序如下:

  1. 我从外部系统接收数据
  2. 我通过一个线程将数据放入一个队列(ConcurrencyQueue)中
  3. 另一个线程从该队列中获取数据,对其进行处理并将其添加到绑定到表的 BindingList 中。

实际的添加发生在一个有 2 个参数的函数中: 1. 包含列项目的列表(项目) 2. 行的颜色。(color)

看起来如下(半伪):

/* Store the color for the row in the color list so it is accessible from the event */  

rowColors.Add(rowColor);    //Class variable that stored the colors of the rows used in the DataGridCellFormatting event

/* Create the row that is to be added. */
ResultRow resultRow = new ResultRow();

foreach(item in items)
{
    resultRow.Set(item); /* It's actually a dictionary because some fields are optional, hence this instead of a     direct constructor call) */
}

bindingList.Add(resultRow);

/* Row coloring based on error is done in the OnCellFormatting() */


/* Auto scroll down */
if (dataGrid.Rows.Count > 0)
{
    dataGrid.FirstDisplayedScrollingRowIndex = dataGrid.Rows.Count - 1;
}

如上面的代码所示,我收到的颜色被添加到一个列表中,该列表用于 datagridview 的事件,如下所示:

void DataGridCellFormattingEvent(object sender, DataGridViewCellFormattingEventArgs e)
{
    // done by column so it happens once per row
    if (e.ColumnIndex == dataGrid.Columns["Errors"].Index)
    {
        dataGrid.Rows[e.RowIndex].DefaultCellStyle.BackColor = rowColors[e.RowIndex];
}
} 

BindingList 定义如下:

BindingList 绑定列表;

其中 ResultRow 是一个具有如下结构的类:

public class ResultRow
{
    private int first = 0;
    private string second = "";
    private UInt64 third = 0;
    private IPAddress fourth = null;
    //etc

    public ResultRow()
    {
    }

    public void Set (<the values>) //In actuallity a KeyValuePair
    {
        //field gets set here
    }

    public UInt64 Third
    {
        get { return third; }
        set { third = value; }
    }

    /* etc. */

我可以做一些相对简单的事情来提高性能吗?我正在考虑可能在处理繁忙时禁用数据网格的绘制,并在完成时绘制。 (虽然不是首选)另一件事可能是不那么频繁地更新,而不是在每个收到的项目之后更新。 (BindingList 似乎会在添加某些内容时自动更新 DataGridView)

我希望有人愿意/能够提供帮助。

-编辑-

当它以上述方式处理数据时,表单的响应能力也很差,尤其是在一段时间之后。 (即使上述过程发生在 backgroundworker(s) 和后台线程中)

【问题讨论】:

    标签: c# performance datagridview drawing bindinglist


    【解决方案1】:

    由于网格中的行数过多,性能可能会在一段时间后下降。你应该试试Virtual Mode

    但首先,尝试推迟网格的更新并批量添加新条目,即降低更新频率。所以,在每次批量更新之前:

    // stop raising update events
    bindingList.RaiseListChangedEvents = false; 
    

    然后:

    // restore update events, raise reset event
    bindingList.RaiseListChangedEvents = true;
    bindingList.ResetBindings() 
    

    在最后一行之后继续滚动到最后一行。

    【讨论】:

      【解决方案2】:

      是的,您可以采取一些措施来加快速度。

      首先 - 虚拟化数据网格。这是 winforms 数据网格的内置机制,它只会填充行并为可见的数据项绘制客户区域。因此,如果您的控件仅显示 20 行(以及其他行的滚动条),那么实际上只有 20 个项目作为 UI 处理到数据网格中。 然后,当您滚动网格以查看其他项目时,数据网格会根据需要填充并显示请求的行。 您需要对此进行一些修改(需要订阅 CellValueNeeded 事件),并且您可能需要编辑您的 bindingsource 数据项。 请参阅http://msdn.microsoft.com/en-us/library/ms171622.aspx 了解更多信息。

      您可以做的第二件事是在填充数据“块”时暂停 UI 更新。 正如您已经指出的,当您向其添加项目时,bindinglist 将自动更新网格。但是通过暂停 UI 更新,然后以一定的时间间隔(比如每秒)重新启用,您将以不太恒定的速率传输数据。 但是请注意,仍然需要对数据进行相同的处理,因此这不太可能完全解决您的数据,并且可能更有效地减少屏幕闪烁。 请参阅Control.SuspendLayout()Control.ResumeLayout() 了解更多信息。

      在我看来,虚拟化将是您最有效的工具,因为它的唯一目的是改进超大型数据集的网格功能。

      【讨论】:

      • 我已经在我的数据网格上应用了暂停/恢复机制。起初,这并没有太大帮助。我现在创建了一个新的后台工作人员,负责在相当大的时间间隔内更新数据网格,这似乎有帮助。 (但是更多的线程和更多的调用。不确定这是否是一件好事..)实际上我之前遇到过那篇及时数据加载文章,它看起来很复杂,所以我希望不必这样做。该示例也是基于数据库的,因此我无法直接应用它。但我想我将不得不尝试弄清楚以进一步提高性能。
      • 很高兴它的帮助。确实,msdn 教程并不总是最有帮助的。 codeproject.com/Articles/23937/… 是一个更好的资源,它不是最好的 codeproject 文章,但应该包含正确的信息。虚拟化相对简单,如果您集中精力通过 CellValueNeeded 为网格提供数据对象属性,您将立即启动并运行。
      • 这似乎是可以理解的。我确实觉得这篇文章缺少一些信息来使它工作。我现在实现了它,但我的数据网格仍然是空的。我在这里发布了我的问题的详细信息:stackoverflow.com/questions/10512981/…
      猜你喜欢
      • 2011-04-16
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-10
      • 2013-03-07
      相关资源
      最近更新 更多