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。 若拋出例外,主要方法會等待記憶體可用後再啟動下一個執行緒。

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 的物件>一節。

透過拋 InsufficientMemoryException 出例外,應用程式可以區分操作無法完成的估計值與可能破壞應用程式狀態的部分完成操作。 這讓應用程式能降低悲觀升級政策的頻率,這可能需要卸載電流 AppDomain 或回收流程。

MemoryFailPoint 檢查所有垃圾回收堆積中是否有足夠的記憶體和連續虛擬位址空間,並可能增加交換檔案的大小。 MemoryFailPoint 不保證記憶體在閘存續期間的長期可用性,但呼叫者應始終使用此 Dispose 方法以確保與 相關的 MemoryFailPoint 資源被釋放。

要使用記憶體閘,你必須建立一個 MemoryFailPoint 物件,並指定下一個操作預期使用的兆位元組(MB)記憶體數量。 若記憶體不足, InsufficientMemoryException 則會拋出例外。

建構子的參數必須是正整數。 負值或 0 會 ArgumentOutOfRangeException 觸發例外。

MemoryFailPoint 運作的細緻度為 16 MB。 小於 16 MB 的值視為 16 MB,其他值則視為 16 MB 的下一個大倍數。

建構函式

名稱 Description
MemoryFailPoint(Int32)

初始化該類別的新實例 MemoryFailPoint ,指定成功執行所需的記憶體量。

方法

名稱 Description
Dispose()

釋放所有由 MemoryFailPoint.

Equals(Object)

判斷指定的 物件是否等於目前的物件。

(繼承來源 Object)
Finalize()

確保當垃圾回收器回收 MemoryFailPoint 物件時,資源會被釋放並執行其他清理作業。

GetHashCode()

做為預設雜湊函式。

(繼承來源 Object)
GetType()

取得目前實例的 Type

(繼承來源 Object)
MemberwiseClone()

建立目前 Object的淺層複本。

(繼承來源 Object)
ToString()

傳回表示目前 物件的字串。

(繼承來源 Object)

適用於