处理非常大的数据集并及时加载

Som*_*ter 9 c# file-io datagridview large-data

我有一个用C#(.NET 4.0)编写的.NET应用程序.在此应用程序中,我们必须从文件中读取大型数据集,并以类似网格的结构显示内容.因此,为了实现这一点,我在表单上放置了一个DataGridView.它有3列,所有列数据都来自文件.最初,该文件有大约600.000条记录,对应于DataGridView中的600.000行.

我很快发现,DataGridView崩溃了这么大的数据集,所以我切换到虚拟模式.为了实现这一点,我首先将文件完全读入3个不同的数组(对应3列),然后触发CellValueNeeded事件,我从数组中提供正确的值.

但是,正如我们很快发现的那样,这个文件中可能有一个巨大的(巨大的!)记录数.当记录大小非常大时,将所有数据读入数组或List <>等似乎是不可行的.我们很快就会遇到内存分配错误.(内存不足异常).

我们卡在那里,但后来意识到,为什么首先将数据全部读入数组,为什么不在CellValueNeeded事件触发时按需读取文件?这就是我们现在所做的:我们打开文件,但不读取任何内容,并且当CellValueNeeded事件触发时,我们先将Seek()放到文件中的正确位置,然后读取相应的数据.

这是我们能想到的最好的,但是,首先这是非常缓慢的,这使得应用程序缓慢且用户不友好.其次,我们不禁认为必须有更好的方法来实现这一目标.例如,某些二进制编辑器(如HXD)对于任何文件大小都非常快,所以我想知道如何实现这一点.

哦,并且为了解决我们的问题,在DataGridView的虚拟模式中,当我们将RowCount设置为文件中的可用行数(例如16.000.000)时,DataGridView甚至需要一段时间来初始化自身.对此"问题"的任何评论也将受到赞赏.

谢谢

Jim*_*hel 5

如果您无法将整个数据集放入内存中,则需要缓冲方案.您的应用程序应该预测用户的操作并提前预读,而不是只读取填充DataGridView响应所需的数据量CellValueNeeded.因此,例如,当程序首次启动时,它应该读取前10,000条记录(或者可能只读取1,000条或者大约100,000条 - 在您的情况下是合理的).然后,CellValueNeeded可以立即从内存中填写请求.

当用户在网格中移动时,您的程序尽可能地比用户领先一步.如果用户跳到你前面可能会有短暂的停顿(比如说,想要从前面跳到最后)并且你必须转到磁盘才能完成请求.

缓冲通常最好由一个单独的线程来完成,尽管如果线程在预期用户的下一个操作时正在读取,同时有时会发生同步,然后用户会做一些完全意外的事情,例如跳转到列表的开头.

除非记录非常大,否则1600万条记录并非真正记录在内存中.或者,如果您的服务器上没有太多内存.当然,List<T>除非T是值类型(结构),否则1600万不能接近a的最大大小.你在这里谈论了多少千兆字节的数据?

  • 你好 Jim,T,是一个带有 4 个双精度浮点数的结构体。因此,4*8*16M = 512MB 的数据。 (2认同)