实现一个算法时,可能事先知道该算法需要大量内存,而且要占用大量内存。可能就这么开始执行算法,如果内存耗尽,CLR会抛出一个OutOfMemoryException。在这种情况下,以前做的大量工作都算是白费了。另外,需要捕捉这个异常,使程序得体的恢复。
System.Runtime命名空间提供了一个MemoryFailPoint类,它允许在开始一个内存消耗巨大的算法之前检查是否有充裕的内存。你可以在MSDN上查看该类。
使用该类的方法非常简单。首先构造该类的一个实例。在构造时,要传递你的算法可能需要的MB数。在内部构造会执行以下检查,按顺序引发相应的行动。
- 系统的分页文件是否有足够的可用空间,而且进程中是否有足够的连续虚拟地址空间来满足需求?注意,会扣除已被另一个MemoryFailPoint构造调用逻辑性保留的内存。
- 如果没有足够的空间,就强制一次垃圾回收,尝试释放一些空间。
- 如果仍然没有足够的分页文件空间,就尝试扩展分页文件,如果分页文件不能扩展到足够大,就抛出一个InsufficientMemoryException
- 如果仍然没有连续的虚拟地址空间,就抛出一个InsufficientMemoryException
- 如果找到了足够大的分页文件空间和虚拟地址空间,就将兆字节数加到MemoryFailPoint类定义的一个私有静态变量上面,从而保留请求的兆字节数,这种加法操作是以一种线程安全的方式进行的,使多个线程能同时构造该类的实例,并确保只要构造器不抛出异常,就能在逻辑上保留他们请求的内存。
如果MemoryFailPoint类的构造器抛出一个InsufficientMemoryException,你的应用程序可释放一些它正在使用的资源,或降低它的性能以降低CLR未来跑出InsufficientMemoryException的机率。InsufficientMemoryException是从OutOfMemoryException派生的。
注意:如果MemoryFailPoint在逻辑上没有抛出异常,表明已经在逻辑上保留了所请求的内存。现在可以开启执行消耗内存大的算法。但要注意,请求的内存尚未物理性的分配。这意味着算法只是更有可能获得所需内存并运行成功。即使构造器没有抛出异常,MemoryFailPoint也不能保证算法获得他所需要的内存。这个类的目的是帮助你写更健壮的应用程序。
执行完算法之后,要在构造的MemoryFailPoint对象上调用Dispose方法。在内部Dispose会以线程安全的方式从MemoryFailPoint类的静态字段中减去保留的字节数,一下演示了MemoryFailPoint类的用法:
static void Main(string[] args)
{
try
{
using (System.Runtime.MemoryFailPoint mfp = new System.Runtime.MemoryFailPoint(1500))
{
//在这里执行内存消耗大的算法。
}
}
catch (InsufficientMemoryException e)
{
Console.WriteLine(e);
}
}