【问题标题】:Dynamically Populated TableLayoutPanel Performance Degredation动态填充的 TableLayoutPanel 性能下降
【发布时间】:2009-03-24 19:11:44
【问题描述】:

我有一个包含 2 列 TableLayoutPanel 的用户控件,并接受命令以动态添加行以显示在单独控件中选择的项目的详细信息。因此,用户将在另一个控件(DataGridView)中选择一行,并在 DataGridView 的 SelectedItemChanged 事件处理程序中清除细节控件,然后为新的选定项重新生成所有行(可能具有完全不同的细节从先前选择的项目中显示)。这在一段时间内效果很好。但是如果我在很长一段时间内从一个选定的项目移动到另一个,刷新会变得非常慢(每次 3-5 秒)。这听起来好像我没有正确处理所有东西,但我无法弄清楚我错过了什么。这是我清除 TableLayoutPanel 的代码:

private readonly List<Control> controls;

public void Clear()
{
    detailTable.Visible = false;
    detailTable.SuspendLayout();
    SuspendLayout();
    detailTable.RowStyles.Clear();
    detailTable.Controls.Clear();
    DisposeAndClearControls();
    detailTable.RowCount = 0;
    detailTable.ColumnCount = 2;
}

private void DisposeAndClearControls()
{
    foreach (Control control in controls)
    {
        control.Dispose();
    }
    controls.Clear();
}

一旦我完成将我想要的所有控件加载到 TableLayoutPanel 中以进行下一个详细显示,这就是我所说的:

public void Render()
{
    detailTable.ResumeLayout(false);
    detailTable.PerformLayout();
    ResumeLayout(false);
    detailTable.Visible = true;
}

我在 TableLayoutPanel 中只使用标签(很少使用文本框),我在创建它们时将标签和文本框添加到控件列表(在 DisposeAndClearControls() 中引用)。我尝试只是迭代 detailTable.Controls 并以这种方式处理它们,但它似乎错过了一半的控件(通过在调试器中单步执行来确定)。这样我就知道我得到了所有这些。

我对提高绘图性能的任何建议感兴趣,尤其是导致多选性能下降的原因。

【问题讨论】:

    标签: c# .net winforms tablelayoutpanel


    【解决方案1】:

    只需使用从 TableLayoutPanel 继承的自定义控件并将 DoubleBuffered 属性设置为 true,效果很好……尤其是当您动态添加或删除行时。

    public CustomLayout()
    {
       this.DoubleBuffered = true;
       InitializeComponent();
    }
    

    【讨论】:

    • 我刚刚在类似的解决方案中使用了这种方法,效果很好。谢谢
    【解决方案2】:

    我对 TableLayout 也有类似的问题。如果我使用 TableLayout.Controls.Clear() 方法,子控件永远不会被释放,但是当我简单地删除 TableLayout 而不清除它时,泄漏就停止了。回想起来,我使用 Clear 方法来防止某种泄漏,这很有趣。

    显然,Clear 方法没有显式处理控件(这是有道理的,因为您从 TableLayout 中删除它们并不意味着您已经完成了它们)并且从 TableLayout 中删除子控件会阻止清理例程在 LayoutTable 本身被处置时处置孩子(它根本不知道它们了)。

    我的建议:删除 detailTable.Controls.Clear(); 行,从父级的 Controls 集合中删除 detailTable 本身并处置它,然后创建一个全新的下一轮的表格布局。也完全失去 DisposeAndClearControls 方法,因为您不需要它。根据我的经验,它运作良好。

    这样,您不必再回收整个用户控件,而只需回收其中的 TableLayout。

    【讨论】:

      【解决方案3】:

      很遗憾,我能提供的唯一建议是自己处理控件的放置。根据我的经验,.NET TableLayoutPanel 虽然非常有用,但它会泄漏一些东西,并且随着它的增长变得非常缓慢(而且达到这一点也不需要不合理数量的单元格)。在设计器中也可以看到这种行为。

      【讨论】:

      • 你似乎是对的。如果我正确读取 VSTS 探查器数据,则它大部分时间都花在 Clear and Visible = true 操作上。
      【解决方案4】:

      我更改了包含表单,以便在每次选择更改时构建我的用户控件的新版本。它处理旧的并构建一个新的。这似乎表现得很好。无论如何,出于性能原因,我最初只重用了一个。显然这并不能提高性能。如果我处理旧的并创建一个新的,性能不会有问题。

      不幸的是,TableLayoutPanel 像这样泄漏。

      【讨论】:

        【解决方案5】:

        我也遇到了同样的问题,找到了一个好方法,不用太多改动:

        在 VB.net 中

        Dim tp As Type = tlpMyPanel.GetType().BaseType
        Dim pi As Reflection.PropertyInfo = _
            tp.GetProperty("DoubleBuffered", _ 
            Reflection.BindingFlags.Instance _
            Or Reflection.BindingFlags.NonPublic)
        pi.SetValue(tlpMyPanel, True, Nothing)
        

        或在 C# 中:

        Type tp = tlpMyPanel.GetType().BaseType;
        System.Reflection.PropertyInfo pi = 
            tp.GetProperty("DoubleBuffered",
            System.Reflection.BindingFlags.Instance 
            | System.Reflection.BindingFlags.NonPublic);
        pi.SetValue(tlpMyPanel, true, null);
        

        【讨论】:

        • 我提交了一个得到回滚的更正,但此代码无法编译。 tlpMyPanel.GetType.BaseType 需要一些 () ....
        【解决方案6】:

        TableLayoutPanel.Controls.Clear() 对我来说很好用,可能是因为我从不同的选项卡中清除了它,而不是显示在其中。

        【讨论】:

          【解决方案7】:
          List<Control> controls = new List<Control>();
          foreach (Control control in tableLayoutPanelEnderecoDetalhes.Controls)
          {
              controls.Add(control);
          }
          
          foreach (Control control in controls)
          {
              control.Dispose();
          }
          

          【讨论】:

          • 迟到的答案审查:请解释这将如何以及为什么会解决所描述的问题,以及它在已经给出的答案之外提供了什么。
          猜你喜欢
          • 1970-01-01
          • 2018-03-25
          • 2015-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多