代码改变世界

预测需求较多内存的操作能否成功

2011-09-06 14:12  Mr.Xer  阅读(381)  评论(0编辑  收藏  举报

  以前,我们会发现这种情况:在实现一个算法时,该算法需要同时使用大量的对象,而这将占用大量的内存。当我们开始执行算法时,如果内存被消耗尽了,CLR就会抛出一个OutOfMemoryException异常。我们不得不做大量的工作来进行恢复,现在,不需要这样做了。我们只需抛出异常,程序会顺利进行恢复。

  在命名空间System.Runtime中有一个MemoryFailPoint类,它在执行内存消耗巨大的算法时为我们提供了这种检测内存不足的能力。下面是该类的形式:

  public sealed class MemoryFailPoint : CritcalFinalizerObject , IDisposable {

    Public MemoryFailPoint( Int32 sizeInMegabytes);

    ~MemoryFailPoint();

    Public void Dispose();

  }

  使用该类的方式非常简单。首先,构建该类的一个实例,并将算法可能需要(如果无法完全确认,则使用上舍入算法(的内存量(M字节)传递给它。该构造器在内部执行下述检查,并相继触发相应的动作:

  1.  系统的页交换文件(paging file)中是否有足够的可用空间?进程中是否有足够的连续虚拟地址空间来满足请求?注意,构造器会扣除已被另一个调用MemoryFailPoint构造器保留的任意数量的内存。

  2.  如果系统的页交换文件中没有足够的空间,则强制执行垃圾收集,试图借此释放一些空间。

  3.  如果系统的页交换文件中仍然没有足够的空间,则尝试扩大系统的页交换文件。如果系统的页交换文件无法扩展到足够大,则抛出一个InsufficientMemory-Exception异常。

  4.  如果进程中没有足够的连续虚拟地址空间,则抛出一个InsufficientMemory-Exception异常。

  5.  如果找到了足够的页交换文件空间和虚拟地址空间,则通过在MemoryFailPoint类中定义的私有静态字段中添加内存量(M字节)类保留所请求的内存。该添加过程是线程安全的,因此多个线程可同时构建该类的一个实例,并且确保在逻辑上他们只保留自己所请求的内存(只要构造器中没有异常抛出)。

  如果MemoryFailPoint类的构造器抛出了一个InsufficientMemoryException异常,那么我们的应用程序可以释放一些它正在使用的资源,或者降低应用程序的性能(较少的缓存数据)以减少CLR未来抛出InsufficientMemoryException异常的可能性。顺便说一下,InsufficientMemoryException异常派生自outofMemoryException异常。

  执行完算法后,应对我们构建的MemoryFailPoint对象调用Dispose方法。从内部实现上讲,Dispose方法减掉(以线程安全的方式)我们在MemoryFailPoint对象的静态字段中保留的内存量(M字节)。下面的代码演示了MemoryFailPoint类的用法:

  using System;

  using System.Runtime;

  public static class Program{

    public static void Main(){

      try{

          //在逻辑上保留1.5GB的内存

          using (MemoryFailPoint mfp = new MemoryFailPoint(1500)) {

            //在这里执行内存消耗大的算法

          }  //Dispose方法将在逻辑上释放这1.5GB的内存

      }

      catch (InsufficientMemoryException e) {

          //无法保留所需的内存

          Console.WriteLine(e);

      }

    }

  }