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

注釈

Note

このクラスは、高度な開発で使用することを目的としています。

MemoryFailPoint クラスのインスタンスを作成すると、メモリ ゲートが作成されます。 メモリ ゲートは、大量のメモリを必要とするアクティビティを開始する前に、十分なリソースをチェックします。 チェックに失敗すると、 InsufficientMemoryException 例外がスローされます。 この例外により、操作が開始されるのを防ぎ、リソースが不足しているためにエラーが発生する可能性が軽減されます。 これにより、パフォーマンスを低下させ、 OutOfMemoryException 例外や、コード内の任意の場所で例外を不適切に処理した結果として発生する可能性のある状態の破損を回避できます。

Important

この型は、IDisposable インターフェイスを実装します。 型の使用が完了したら、直接または間接的に破棄する必要があります。 型を直接破棄するには、Disposetry/ ブロックでその catch メソッドを呼び出します。 間接的に破棄するには、using (C#) や Using (Visual Basic) などの言語コンストラクトを使用します。 詳細については、 IDisposable インターフェイスのトピックの「IDisposable を実装するオブジェクトの使用」セクションを参照してください。

InsufficientMemoryException例外をスローすることで、アプリケーションは、操作を完了できないという見積もりと、アプリケーションの状態を破損している可能性がある部分的に完了した操作を区別できます。 これにより、アプリケーションはペシミスティック エスカレーション ポリシーの頻度を減らすことができます。このポリシーでは、現在の AppDomain のアンロードやプロセスのリサイクルが必要になる場合があります。

MemoryFailPoint は、十分なメモリと連続する仮想アドレス空間がすべてのガベージ コレクション ヒープで使用できるかどうかを確認します。また、スワップ ファイルのサイズが大きくなる可能性があります。 MemoryFailPoint では、ゲートの有効期間中のメモリの長期的な可用性に関する保証はありませんが、呼び出し元は常に Dispose メソッドを使用して、 MemoryFailPoint に関連付けられているリソースが確実に解放されるようにする必要があります。

メモリ ゲートを使用するには、 MemoryFailPoint オブジェクトを作成し、次の操作で使用するメモリのメガバイト数 (MB) を指定する必要があります。 十分なメモリが使用できない場合は、 InsufficientMemoryException 例外がスローされます。

コンストラクターのパラメーターは正の整数である必要があります。 負の値または 0 を指定すると、 ArgumentOutOfRangeException 例外が発生します。

MemoryFailPoint は、16 MB の粒度で動作します。 16 MB 未満の値はすべて 16 MB として扱われ、その他の値は 16 MB の次に大きい倍数として扱われます。

コンストラクター

名前 説明
MemoryFailPoint(Int32)

正常に実行するために必要なメモリ量を指定して、 MemoryFailPoint クラスの新しいインスタンスを初期化します。

メソッド

名前 説明
Dispose()

MemoryFailPointによって使用されるすべてのリソースを解放します。

Equals(Object)

指定したオブジェクトが現在のオブジェクトと等しいかどうかを判断します。

(継承元 Object)
Finalize()

ガベージ コレクターが MemoryFailPoint オブジェクトを再利用するときに、リソースが解放され、その他のクリーンアップ操作が実行されるようにします。

GetHashCode()

既定のハッシュ関数として機能します。

(継承元 Object)
GetType()

現在のインスタンスの Type を取得します。

(継承元 Object)
MemberwiseClone()

現在の Objectの簡易コピーを作成します。

(継承元 Object)
ToString()

現在のオブジェクトを表す文字列を返します。

(継承元 Object)

適用対象