可以并且将C#向页面文件写入对象

本文关键字:文件 对象 | 更新日期: 2023-09-27 18:21:40

我想知道C#是否可以将对象写入页面文件。

我已经知道,.NET应用程序的虚拟机被限制为只允许一个对象使用2GB的内存,并且早在那之前就会耗尽内存,即使在64位版本的Windows上也是如此。

然而,我需要能够加载大量的字符串(不是一个大字符串,而是许多小字符串),我想知道是否可以加载它们,并将它们写入交换空间,直到再次需要它们为止(不幸的是,我不可能阻止加载所有字符串,因为这是由调用我正在处理的代码的应用程序强制加载的)。

为了制作它的原型,我试着看看下面的程序是否也会耗尽内存(它会耗尽内存),尽管它没有试图分配一个巨大的字符串:

public static void Main()
{
        ICollection<StringBuilder> builders = new LinkedList<StringBuilder>();
        double used_ram = 2*1024*1024*1024L;
        int blocksize = 12800000;
        int blocks = (int) (used_ram/blocksize);
        for (int i = 1; i < blocks ; i++)
        {
            StringBuilder sb = new StringBuilder(blocksize/2);
            builders.Add(sb);
        }
        Console.ReadLine();
}

我希望字符串能被写入交换空间,并想知道是否有任何方法可以强制应用程序这样做。

编辑:将交换文件的使用改为页面文件(感谢您的澄清)。

好的,所以我想强调一下我的问题:如果运行时的唯一限制是ONE对象不能分配超过2 gb的内存——为什么上面的代码会耗尽内存——因为列表通过引用所有的字符串生成器来遍历2 gb的存储器?

可以并且将C#向页面文件写入对象

简短回答:不,你不能。

使用交换不是应用程序所做的事情:操作系统的内存管理系统对此负责。

如果您需要在进程中一次加载超过2GB的数据(而不是根据需要按块从磁盘中检索数据),那么您就有严重的设计问题。


编辑:由于您已经在使用64位操作系统,请确保您正在为x64平台(或AnyCPU)编译应用程序,并且您的应用程序不是使用WOW64作为32位进程运行的。

我认为你的问题相当于:

一个32位.NET应用程序可以寻址超过2GB的内存。

是的,可以通过调整分配给用户应用程序和操作系统的内存分配来增加应用程序可以处理的内存量,但我不建议在大多数情况下这样做,因为这可能会导致O/S功能(如网络)出现微妙而不那么微妙的问题。有关/3GB/USERVA交换机的详细信息,请参阅本文。这将允许您的应用程序处理3GB(减去开销)内存,而不是2GB。

您可以使用的工具有:

  • 切换到64位.NET
  • 使用内存映射文件
  • 编写自己的寻呼系统
  • 使用一些后备存储,例如文件系统、数据库

您可以利用所有windows内存管理功能,并在系统允许的范围内分配尽可能多的内存,但您所做的工作需要某种类型的磁盘刷新系统。即使你可以让windows分配这么大的对象,你的性能也会很糟糕。有许多现成的系统(称为数据库),允许您在其中放入大量数据,并在很短的时间内访问它们。

您可能做错了什么。我已经编写了使用超过2GB内存的.net应用程序。如果您运行的是64位窗口,那么您的应用程序没有理由不能使用更多的内存。

我建议您应该编写自己的缓存类。例如,请查看此处的

我认为在.Net应用程序级别上与您的方法接近的是MemoryMappedFile

但这意味着应用程序不会尝试一次性获取所有字符串。