MemoryFailPoint Класс

Определение

Проверяет наличие достаточного количество ресурсов памяти перед выполнением операции. Этот класс не наследуется.

public ref class MemoryFailPoint sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject, IDisposable
public sealed class MemoryFailPoint : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, IDisposable
type MemoryFailPoint = class
    inherit CriticalFinalizerObject
    interface IDisposable
Public NotInheritable Class MemoryFailPoint
Inherits CriticalFinalizerObject
Implements IDisposable
Наследование
Реализации

Примеры

MemoryFailPoint позволяет приложению замедлять работу, чтобы избежать нехватки памяти при повреждении. Его следует использовать в лексической области. В следующем примере запускается поток для обработки элементов в рабочей очереди. Перед запуском каждого потока проверяются доступные ресурсы памяти с помощью MemoryFailPoint. При возникновении исключения метод main ожидает, пока не будет доступна память, прежде чем запускать следующий поток.

using System;
using System.Runtime;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.Collections;

class MemoryFailPointExample
{
    // Allocate in chunks of 64 megabytes.
    private const uint chunkSize = 64 << 20;
    // Use more than the total user-available address space (on 32 bit machines)
    // to drive towards getting an InsufficientMemoryException.
    private const uint numWorkItems = 1 + ((1U << 31) / chunkSize);
    static Queue workQueue = new Queue(50);

    // This value can be computed separately and hard-coded into the application.
    // The method is included to illustrate the technique.
    private static int EstimateMemoryUsageInMB()
    {
        int memUsageInMB = 0;

        long memBefore = GC.GetTotalMemory(true);
        int numGen0Collections = GC.CollectionCount(0);
        // Execute a test version of the method to estimate memory requirements.
        // This test method only exists to determine the memory requirements.
        ThreadMethod();
        // Includes garbage generated by the worker function.
        long memAfter = GC.GetTotalMemory(false);
        // If a garbage collection occurs during the measuring, you might need a greater memory requirement.
        Console.WriteLine("Did a GC occur while measuring?  {0}", numGen0Collections == GC.CollectionCount(0));
        // Set the field used as the parameter for the MemoryFailPoint constructor.
        long memUsage = (memAfter - memBefore);
        if (memUsage < 0)
        {
            Console.WriteLine("GC's occurred while measuring memory usage.  Try measuring again.");
            memUsage = 1 << 20;
        }

        // Round up to the nearest MB.
        memUsageInMB = (int)(1 + (memUsage >> 20));
        Console.WriteLine("Memory usage estimate: {0} bytes, rounded to {1} MB", memUsage, memUsageInMB);
        return memUsageInMB;
    }

    static void Main()
    {
        Console.WriteLine("Attempts to allocate more than 2 GB of memory across worker threads.");
        int memUsageInMB = EstimateMemoryUsageInMB();

        // For a production application consider using the threadpool instead.
        Thread[] threads = new Thread[numWorkItems];
        // Create a work queue to be processed by multiple threads.
        int n = 0;
        for (n = 0; n < numWorkItems; n++)
            workQueue.Enqueue(n);
        // Continue to launch threads until the work queue is empty.
        while (workQueue.Count > 0)
        {
            Console.WriteLine(" GC heap (live + garbage): {0} MB", GC.GetTotalMemory(false) >> 20);
            MemoryFailPoint memFailPoint = null;
            try
            {
                // Check for available memory.
                memFailPoint = new MemoryFailPoint(memUsageInMB);
                n = (int)workQueue.Dequeue();
                threads[n] =
                    new Thread(new ParameterizedThreadStart(ThreadMethod));
                WorkerState state = new WorkerState(n, memFailPoint);
                threads[n].Start(state);
                Thread.Sleep(10);
            }
            catch (InsufficientMemoryException e)
            {
                // MemoryFailPoint threw an exception, handle by sleeping for a while,  then
                // continue processing the queue.
                Console.WriteLine("Expected InsufficientMemoryException thrown.  Message: " + e.Message);
                // We could optionally sleep until a running worker thread
                // has finished, like this:  threads[joinCount++].Join();
                Thread.Sleep(1000);
            }
        }

        Console.WriteLine("WorkQueue is empty - blocking to ensure all threads quit (each thread sleeps for 10 seconds)");
        foreach (Thread t in threads)
            t.Join();
        Console.WriteLine("All worker threads are finished - exiting application.");
    }

    // Test version of the working code to determine memory requirements.
    static void ThreadMethod()
    {
        byte[] bytes = new byte[chunkSize];
    }

    internal class WorkerState
    {
        internal int _threadNumber;
        internal MemoryFailPoint _memFailPoint;

        internal WorkerState(int threadNumber, MemoryFailPoint memoryFailPoint)
        {
            _threadNumber = threadNumber;
            _memFailPoint = memoryFailPoint;
        }

        internal int ThreadNumber
        {
            get { return _threadNumber; }
        }

        internal MemoryFailPoint MemoryFailPoint
        {
            get { return _memFailPoint; }
        }
    }

    // The method that does the work.
    static void ThreadMethod(Object o)
    {
        WorkerState state = (WorkerState)o;
        Console.WriteLine("Executing ThreadMethod, " +
            "thread number {0}.", state.ThreadNumber);
        byte[] bytes = null;
        try
        {
            bytes = new byte[chunkSize];
            // Allocated all the memory needed for this workitem.
            // Now dispose of the MemoryFailPoint, then process the workitem.
            state.MemoryFailPoint.Dispose();
        }
        catch (OutOfMemoryException oom)
        {
            Console.Beep();
            Console.WriteLine("Unexpected OutOfMemory exception thrown: " + oom);
        }

        // Do work here, possibly taking a lock if this app needs
        // synchronization between worker threads and/or the main thread.

        // Keep the thread alive for awhile to simulate a running thread.
        Thread.Sleep(10000);

        // A real thread would use the byte[], but to be an illustrative sample,
        // explicitly keep the byte[] alive to help exhaust the memory.
        GC.KeepAlive(bytes);
        Console.WriteLine("Thread {0} is finished.", state.ThreadNumber);
    }
}

Комментарии

Примечание

Этот класс предназначен для использования в расширенной разработке.

При создании экземпляра MemoryFailPoint класса создается шлюз памяти. Шлюз памяти проверяет наличие достаточных ресурсов перед инициализацией действия, требующего большого объема памяти. Сбой проверки приводит к возникновению InsufficientMemoryException исключения. Это исключение предотвращает запуск операции и снижает вероятность сбоя из-за нехватки ресурсов. Это позволяет снизить производительность, чтобы избежать OutOfMemoryException исключения и любого повреждения состояния, которое может быть вызвано неправильной обработкой исключения в произвольных местах в коде.

Важно!

Этот тип реализует интерфейс IDisposable. По окончании использования выдаленную ему память следует прямо или косвенно освободить. Чтобы сделать это прямо, вызовите его метод Dispose в блоке try/catch. Чтобы сделать это косвенно, используйте языковые конструкции, такие как using (в C#) или Using (в Visual Basic). Дополнительные сведения см. в разделе "Использование объекта, реализующего IDisposable" в статье об интерфейсе IDisposable.

Создавая InsufficientMemoryException исключение, приложение может различать оценку того, что операция не сможет завершиться, и частично завершенную операцию, которая могла повредить состояние приложения. Это позволяет приложению уменьшить частоту пессимистичной политики эскалации, что может потребовать выгрузки текущего AppDomain или перезапуска процесса.

MemoryFailPoint проверяет наличие достаточного объема памяти и последовательного виртуального адресного пространства во всех кучах сборки мусора и может увеличить размер файла подкачки. MemoryFailPoint не дает никаких гарантий относительно долгосрочной доступности памяти в течение времени существования шлюза, но вызывающие абоненты должны всегда использовать Dispose метод , чтобы обеспечить освобождение ресурсов, связанных с MemoryFailPoint .

Чтобы использовать шлюз памяти, необходимо создать MemoryFailPoint объект и указать количество мегабайт (МБ) памяти, которое, как ожидается, будет использоваться следующей операцией. Если недостаточно памяти, InsufficientMemoryException возникает исключение.

Параметр конструктора должен быть положительным целым числом. Отрицательное значение вызывает ArgumentOutOfRangeException исключение.

MemoryFailPoint работает с степенью детализации 16 МБ. Все значения меньше 16 МБ обрабатываются как 16 МБ, а другие — как следующие значения, кратные 16 МБ.

Конструкторы

MemoryFailPoint(Int32)

Инициализирует новый экземпляр класса MemoryFailPoint, указывающий объем памяти, необходимый для успешного выполнения.

Методы

Dispose()

Освобождает все ресурсы, занятые модулем MemoryFailPoint.

Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
Finalize()

Обеспечивает освобождение ресурсов и выполнение других завершающих операций, когда сборщик мусора восстанавливает объект MemoryFailPoint.

GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetType()

Возвращает объект Type для текущего экземпляра.

(Унаследовано от Object)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
ToString()

Возвращает строку, представляющую текущий объект.

(Унаследовано от Object)

Применяется к