我如何使用MemoryFailPoint?

MemoryFailPoint (MSDN) “ 在执行操作之前检查足够的内存资源。”

但它是如何实际使用的呢?

MemoryFailPoint是否为我创建的下一个大对象自动保留了一些内存? 或者它只是检查内存是否是免费的,而不是保留它?

它是否检查物理内存,物理内存加页面文件,虚拟地址空间或其他完全?

我什么时候处理它? 我是否需要在实际创建需要大量内存的对象之前部署MemoryFailPoint ,还是必须在部署MemoryFailPoint之前创建对象?

例如

 try { using (MemoryFailPoint mem = new MemoryFailPoint(500)) { // allocate big object here? } } catch (InsufficientMemoryException e) { // ... } // or allocate big object here? // or allocate big object on another thread? 

同一进程中的另一个线程是否可以窃取我用MemoryFailPoint保留的内存,或者MemoryFailPoint是否为当前线程专门保留内存?

如果没有丢弃MemoryFailPoint会发生什么? 一个不相关的MemoryFailPoint本身会消耗大量内存吗?

MemoryFailPoint的源代码可在.NET Source中找到 。 课程开头的描述性评论回答了你的问题。 我在这里复制该评论以便于参考:

此类允许应用程序在启动某些活动之前失败。 我们的想法是提前失败,而不是在一些长时间运行的操作中失败,以提高应用程序的生存能力,并确保您不必编写棘手的代码来处理应用程序代码中的任何位置的OOM(这意味着状态损坏,这意味着您应该卸载appdomain,如果您有一个事务处理环境以确保单个事务的回滚)。 这是一个不完整的工具,可以尝试将所有OOM故障从工作方法中的任何位置提升到更容易处理OOM故障的特定点,并且如果可能会失败,您可以选择不启动工作项。 这无助于直接执行代码(除了帮助避免AD卸载)。 重点是避免在可能失败的情况下开始工作。
企业服务团队在未受管理的世界中有效地使用了这些存储器门十年。

在Whidbey中,我们只需检查操作系统页面文件中是否有足够的可用内存,并尝试确保进程的地址空间中有足够的可用空间(同时检查地址空间碎片)。 我们不会提交或保留任何记忆。 为了避免使用其他线程使用MemoryFailPoints,我们还将通过所有当前活动的MemoryFailPoints跟踪进程范围内的“保留”内存量。 这有两个问题:

  1. This can account for memory twice. If a thread creates a MemoryFailPoint for 100 MB then allocates 99 MB, we'll see 99 MB less free memory and 100 MB less reserved memory. Yet, subtracting off the 100 MB is necessary because the thread may not have started allocating memory yet. Disposing of this class immediately after front-loaded allocations have completed is a great idea. 2. This is still vulnerable to ----s with other threads that don't use MemoryFailPoints. 

所以这堂课远非完美。 但是,有意义地降低托管应用程序中OutOfMemoryExceptions的频率可能已经足够了。

在Orcas或更高版本中,我们可能会从OS分配一些内存并将其添加到此线程的分配上下文中。 显然,在这一点上,当我们释放这块内存时,我们需要一些传达方式。 因此,我们在Whidbey中实现了此类型的IDisposable,并期望所有用户在using块中调用它来为其内存使用提供词法范围。 对Dispose的调用(使用using块隐含)将使我们有机会释放这个内存。 我们预计这将为我们提供在未来版本中更有效设计的可能性。

在Orcas中,我们可能还需要区分进入普通托管堆的分配与大对象堆之间的分配,或者我们应该考虑在两个位置检查足够的可用空间(进行任何适当的调整以确保内存是连续的) 。

使用模式如下:

 const int sizeMB = 500; using (MemoryFailPoint mem = new MemoryFailPoint(sizeMB)) { // Allocate sizeMB - large object here. The allocation is *likely* going to succeed. } 

当MemoryFailPoint构造函数失败时,大对象分配很可能抛出OOM。 即使成功,它也会使该过程对其他(甚至更小的)内存分配操作更不稳定。

在我的16 GB Windows环境中,以下示例生成InsufficientMemoryException,比没有MemoryFailPoint的OOM(步骤= 6)更早的一次迭代(步骤= 5):

  List arrays = new List(); const int size = int.MaxValue/2; const int sizeMB = size / 1024 / 1024; for(int step = 0; step < 10000; step++) { using (new MemoryFailPoint(sizeMB)) { arrays.Add(new byte[size]); } }