【问题标题】:DataGridView Loading Images OutOfMemory ExceptionDataGridView 加载图像 OutOfMemory 异常
【发布时间】:2014-08-10 23:36:49
【问题描述】:

我有一个绑定到 DataGridView 的 DataTable。 DataTable 最多填充 30000 行。 DataGridView 应在填充时显示 DataTable 的内容,这可能需要 3 分钟,因为某些计算过程。

每一行包含文本单元格和两个图像单元格。一开始我将所有图像直接加载到数据表中,但在某些时候(约 10000 行)程序崩溃了,因为系统内存不足。所以我稍微调整了我的代码。问题是,图像消耗了大量内存。现在我只加载用户可以看到的图像。这有很大帮助,并且系统不再在加载 30000 行时崩溃。

只有在大量滚动行时才会出现此问题。我使用 Alireza Maddah 提供的代码设置图像:

public void GetVisibleCells(DataGridView dgv)
{´
    ClearImages()
    var vivibleRowsCount = dgv.DisplayedRowCount(true);
    var firstDisplayedRowIndex = dgv.FirstDisplayedCell.RowIndex;
    var lastvibileRowIndex = (firstDisplayedRowIndex + vivibleRowsCount) - 1;
    for (int rowIndex = firstDisplayedRowIndex; rowIndex <= lastvibileRowIndex; rowIndex++)
    {
        var cells = dgv.Rows[rowIndex].Cells;
        foreach (DataGridViewCell cell in cells)
        {
            if (cell.Displayed)
            {
                // This cell is visible...
                // SET IMAGES TO ROW AND SAVE INDEX
            }
        }
    }
}

How to find out which DataGridView rows are currently onscreen?

这段代码绑定了滚动事件。如果行对用户可见,我设置图像并将行的索引保存到列表中。在设置图像之前,我调用 ClearImages()。 此函数使用列表中的索引条目将所有包含图像的行设置为空。

我认为将变量设置为 null 不会释放内存,但这只是我的第一个想法。你怎么看?有任何想法吗?

我不能使用分页或虚拟模式...

【问题讨论】:

  • 您是否考虑过将缩略图加载到单元格而不是整个图像文件中?

标签: c# datagridview datatable out-of-memory virtual


【解决方案1】:

您应该使用DataGrid.AllowPaging Property 来拆分内容页面(例如每页 100 个图像),这样可以防止内存不足异常。您可以尝试处理旧的可见单元格图像, 另见GC.Collect() not collecting immediately?

【讨论】:

  • 感谢您的链接。我会投票给你并改进答案。
【解决方案2】:

尝试

private void ClearNotVisibleImages()
{
   foreach(var row in this.GetNotVisibleDataRowsWithImages())
   {
      var cell = row["Image"];      
      Image image = (Image)(cell .Content);           

      cell.Content = null;
      image.Dispose();
   }


   // If it will be really needed
   GC.Collect();
   // Improved Thanks @rentanadviser
   GC.WaitForPendingFinalizers();
   GC.Collect();
}

【讨论】:

  • 我发现我将错误的单元格设置为 null...但是我集成了 dispose() 从而进一步提高了性能。谢谢!!!
【解决方案3】:

确保图像没有被任何东西链接。您也可以在清除图像后调用GC.Collect() 来清理大对象堆。但是,这会减慢响应速度。另外,我会先检查哪些图像不再可见,然后只清除那些而不是全部。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2016-01-01
    相关资源
    最近更新 更多