DataGridView加载图像OutOfMemory异常

时间:2014-06-20 08:51:50

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

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

每行包含文本单元格和两个图像单元格。在开始时我将所有图像直接加载到DataTable,但在某些时候(~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并不能释放内存,但这只是我的第一个想法。你怎么看?有任何想法吗?

我无法使用分页或虚拟模式...

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

尝试

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();
}

答案 2 :(得分:0)

确保图像没有任何关联。清除图像后,也可以调用GC.Collect()来清理大对象堆。但是,这会降低响应速度。此外,我会首先检查哪些图像不再可见,只清除那些图像而不是所有图像。

相关问题