我有一个绑定到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并不能释放内存,但这只是我的第一个想法。你怎么看?有任何想法吗?
我无法使用分页或虚拟模式...
答案 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()
来清理大对象堆。但是,这会降低响应速度。此外,我会首先检查哪些图像不再可见,只清除那些图像而不是所有图像。