MemoryFailPoint Classe

Définition

Contrôle que les ressources mémoire sont suffisantes avant d'exécuter une opération. Cette classe ne peut pas être héritée.

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
Héritage
Implémente

Exemples

MemoryFailPoint permet à une application de se ralentir pour éviter de manquer de mémoire de manière endommagée. Il doit être utilisé dans une étendue lexicale. L’exemple suivant lance des threads pour traiter des éléments dans une file d’attente de travail. Avant le lancement de chaque thread, les ressources de mémoire disponibles sont vérifiées à l’aide de MemoryFailPoint. Si une exception est levée, la méthode main attend que la mémoire soit disponible avant de lancer le thread suivant.

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);
    }
}

Remarques

Notes

Cette classe est destinée à être utilisée dans le développement avancé.

La création d’une instance de la MemoryFailPoint classe crée une porte mémoire. Une porte de mémoire recherche suffisamment de ressources avant de lancer une activité qui nécessite une grande quantité de mémoire. L’échec de la vérification entraîne la levée d’une InsufficientMemoryException exception. Cette exception empêche le démarrage d’une opération et réduit le risque d’échec en raison d’un manque de ressources. Cela vous permet de réduire les performances afin d’éviter une OutOfMemoryException exception et toute altération de l’état pouvant résulter d’une gestion incorrecte de l’exception dans des emplacements arbitraires dans votre code.

Important

Ce type implémente l'interface IDisposable. Une fois que vous avez fini d’utiliser le type, vous devez le supprimer directement ou indirectement. Pour supprimer directement le type Dispose, appelez sa méthode dans un bloc try/catch. Pour la supprimer indirectement, utilisez une construction de langage telle que using (dans C#) ou Using (dans Visual Basic). Pour plus d’informations, consultez la section « Utilisation d’un objet qui implémente IDisposable » dans la rubrique de l’interface IDisposable.

En lisant une InsufficientMemoryException exception, une application peut faire la distinction entre une estimation qu’une opération ne sera pas en mesure de se terminer et une opération partiellement terminée qui a peut-être endommagé l’état de l’application. Cela permet à une application de réduire la fréquence d’une stratégie d’escalade pessimiste, ce qui peut nécessiter le déchargement du courant AppDomain ou le recyclage du processus.

MemoryFailPoint vérifie si la mémoire et l’espace d’adressage virtuel consécutifs sont disponibles dans tous les tas de garbage collection et peuvent augmenter la taille du fichier d’échange. MemoryFailPoint n’offre aucune garantie concernant la disponibilité à long terme de la mémoire pendant la durée de vie de la porte, mais les appelants doivent toujours utiliser la Dispose méthode pour s’assurer que les ressources associées à MemoryFailPoint sont libérées.

Pour utiliser une porte de mémoire, vous devez créer un MemoryFailPoint objet et spécifier le nombre de mégaoctets (Mo) de mémoire que l’opération suivante est censée utiliser. Si la mémoire est insuffisante, une InsufficientMemoryException exception est levée.

Le paramètre du constructeur doit être un entier positif. Une valeur négative déclenche une ArgumentOutOfRangeException exception.

MemoryFailPoint fonctionne à une granularité de 16 Mo. Toutes les valeurs inférieures à 16 Mo sont traitées comme 16 Mo, tandis que les autres valeurs sont traitées comme le prochain plus grand multiple de 16 Mo.

Constructeurs

MemoryFailPoint(Int32)

Initialise une nouvelle instance de la classe MemoryFailPoint, en spécifiant la quantité de mémoire requise pour réussir une exécution.

Méthodes

Dispose()

Libère toutes les ressources utilisées par MemoryFailPoint.

Equals(Object)

Détermine si l'objet spécifié est égal à l'objet actuel.

(Hérité de Object)
Finalize()

Vérifie que les ressources sont libérées et que toute autre opération de nettoyage est effectuée quand le garbage collector récupère l'objet MemoryFailPoint.

GetHashCode()

Fait office de fonction de hachage par défaut.

(Hérité de Object)
GetType()

Obtient le Type de l'instance actuelle.

(Hérité de Object)
MemberwiseClone()

Crée une copie superficielle du Object actuel.

(Hérité de Object)
ToString()

Retourne une chaîne qui représente l'objet actuel.

(Hérité de Object)

S’applique à