語言

GC.RegisterForFullGCNotification(Int32, Int32) 方法

定義

規定當條件支持全面垃圾收集且收集完成時,應提出垃圾收集通知。

public:
 static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold);
public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold);
[System.Security.SecurityCritical]
public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold);
static member RegisterForFullGCNotification : int * int -> unit
[<System.Security.SecurityCritical>]
static member RegisterForFullGCNotification : int * int -> unit
Public Shared Sub RegisterForFullGCNotification (maxGenerationThreshold As Integer, largeObjectHeapThreshold As Integer)

參數

maxGenerationThreshold
Int32

一個介於 1 到 99 之間的數字,指定何時應該根據第 2 代分配的物件來通知。

largeObjectHeapThreshold
Int32

一個介於 1 到 99 之間的數字,指定何時應根據大物件堆中分配的物件來發出通知。

屬性

例外狀況

maxGenerationThreshold 或 largeObjectHeapThreshold 不介於1到99之間。

當啟用並行垃圾回收時,此成員無法使用。 請參閱 <gcConcurrent> 執行時設定,了解如何停用並行垃圾回收。

範例

以下範例說明如何註冊垃圾回收通知並啟動執行緒以監控垃圾回收通知的狀態。 此程式碼範例是垃圾 回收通知 主題中提供較大範例的一部分。

using System;
using System.Collections.Generic;
using System.Threading;

namespace GCNotify
{
    class Program
    {
        // Variable for continual checking in the
        // While loop in the WaitForFullGCProc method.
        static bool checkForNotify = false;

        // Variable for suspending work
        // (such servicing allocated server requests)
        // after a notification is received and then
        // resuming allocation after inducing a garbage collection.
        static bool bAllocate = false;

        // Variable for ending the example.
        static bool finalExit = false;

        // Collection for objects that
        // simulate the server request workload.
        static List<byte[]> load = new List<byte[]>();

        public static void Main(string[] args)
        {
            try
            {
                // Register for a notification.
                GC.RegisterForFullGCNotification(10, 10);
                Console.WriteLine("Registered for GC notification.");

                checkForNotify = true;
                bAllocate = true;

                // Start a thread using WaitForFullGCProc.
                Thread thWaitForFullGC = new Thread(new ThreadStart(WaitForFullGCProc));
                thWaitForFullGC.Start();

                // While the thread is checking for notifications in
                // WaitForFullGCProc, create objects to simulate a server workload.
                try
                {

                    int lastCollCount = 0;
                    int newCollCount = 0;

                    while (true)
                    {
                        if (bAllocate)
                        {
                            load.Add(new byte[1000]);
                            newCollCount = GC.CollectionCount(2);
                            if (newCollCount != lastCollCount)
                            {
                                // Show collection count when it increases:
                                Console.WriteLine("Gen 2 collection count: {0}", GC.CollectionCount(2).ToString());
                                lastCollCount = newCollCount;
                            }

                            // For ending the example (arbitrary).
                            if (newCollCount == 500)
                            {
                                finalExit = true;
                                checkForNotify = false;
                                break;
                            }
                        }
                    }
                }
                catch (OutOfMemoryException)
                {
                    Console.WriteLine("Out of memory.");
                }

                finalExit = true;
                checkForNotify = false;
                GC.CancelFullGCNotification();
            }
            catch (InvalidOperationException invalidOp)
            {

                Console.WriteLine("GC Notifications are not supported while concurrent GC is enabled.\n"
                    + invalidOp.Message);
            }
        }

        public static void OnFullGCApproachNotify()
        {

            Console.WriteLine("Redirecting requests.");

            // Method that tells the request queuing
            // server to not direct requests to this server.
            RedirectRequests();

            // Method that provides time to
            // finish processing pending requests.
            FinishExistingRequests();

            // This is a good time to induce a GC collection
            // because the runtime will induce a full GC soon.
            // To be very careful, you can check precede with a
            // check of the GC.GCCollectionCount to make sure
            // a full GC did not already occur since last notified.
            GC.Collect();
            Console.WriteLine("Induced a collection.");
        }

        public static void OnFullGCCompleteEndNotify()
        {
            // Method that informs the request queuing server
            // that this server is ready to accept requests again.
            AcceptRequests();
            Console.WriteLine("Accepting requests again.");
        }

        public static void WaitForFullGCProc()
        {
            while (true)
            {
                // CheckForNotify is set to true and false in Main.
                while (checkForNotify)
                {
                    // Check for a notification of an approaching collection.
                    GCNotificationStatus s = GC.WaitForFullGCApproach();
                    if (s == GCNotificationStatus.Succeeded)
                    {
                        Console.WriteLine("GC Notification raised.");
                        OnFullGCApproachNotify();
                    }
                    else if (s == GCNotificationStatus.Canceled)
                    {
                        Console.WriteLine("GC Notification cancelled.");
                        break;
                    }
                    else
                    {
                        // This can occur if a timeout period
                        // is specified for WaitForFullGCApproach(Timeout)
                        // or WaitForFullGCComplete(Timeout)
                        // and the time out period has elapsed.
                        Console.WriteLine("GC Notification not applicable.");
                        break;
                    }

                    // Check for a notification of a completed collection.
                    GCNotificationStatus status = GC.WaitForFullGCComplete();
                    if (status == GCNotificationStatus.Succeeded)
                    {
                        Console.WriteLine("GC Notification raised.");
                        OnFullGCCompleteEndNotify();
                    }
                    else if (status == GCNotificationStatus.Canceled)
                    {
                        Console.WriteLine("GC Notification cancelled.");
                        break;
                    }
                    else
                    {
                        // Could be a time out.
                        Console.WriteLine("GC Notification not applicable.");
                        break;
                    }
                }

                Thread.Sleep(500);
                // FinalExit is set to true right before
                // the main thread cancelled notification.
                if (finalExit)
                {
                    break;
                }
            }
        }

        private static void RedirectRequests()
        {
            // Code that sends requests
            // to other servers.

            // Suspend work.
            bAllocate = false;
        }

        private static void FinishExistingRequests()
        {
            // Code that waits a period of time
            // for pending requests to finish.

            // Clear the simulated workload.
            load.Clear();
        }

        private static void AcceptRequests()
        {
            // Code that resumes processing
            // requests on this server.

            // Resume work.
            bAllocate = true;
        }
    }
}
open System
open System.Threading

// Variable for continual checking in the
// While loop in the WaitForFullGCProc method.
let mutable checkForNotify = false

// Variable for suspending work
// (such servicing allocated server requests)
// after a notification is received and then
// resuming allocation after inducing a garbage collection.
let mutable bAllocate = false

// Variable for ending the example.
let mutable finalExit = false

// Collection for objects that simulate the server request workload.
let load = ResizeArray<byte []>()


let redirectRequests () =
    // Code that sends requests
    // to other servers.

    // Suspend work.
    bAllocate <- false

let finishExistingRequests () =
    // Code that waits a period of time
    // for pending requests to finish.

    // Clear the simulated workload.
    load.Clear()

let acceptRequests () =
    // Code that resumes processing
    // requests on this server.

    // Resume work.
    bAllocate <- true

let onFullGCApproachNotify () =
    printfn "Redirecting requests."

    // Method that tells the request queuing
    // server to not direct requests to this server.
    redirectRequests ()

    // Method that provides time to
    // finish processing pending requests.
    finishExistingRequests ()

    // This is a good time to induce a GC collection
    // because the runtime will induce a full GC soon.
    // To be very careful, you can check precede with a
    // check of the GC.GCCollectionCount to make sure
    // a full GC did not already occur since last notified.
    GC.Collect()
    printfn "Induced a collection."


let onFullGCCompleteEndNotify () =
    // Method that informs the request queuing server
    // that this server is ready to accept requests again.
    acceptRequests ()
    printfn "Accepting requests again."

let waitForFullGCProc () =
    let mutable broken = false

    while not broken do
        let mutable broken = false
        // CheckForNotify is set to true and false in Main.
        while checkForNotify && not broken do
            // Check for a notification of an approaching collection.
            match GC.WaitForFullGCApproach() with
            | GCNotificationStatus.Succeeded ->
                printfn "GC Notification raised."
                onFullGCApproachNotify ()
                // Check for a notification of a completed collection.
                match GC.WaitForFullGCComplete() with
                | GCNotificationStatus.Succeeded ->
                    printfn "GC Notification raised."
                    onFullGCCompleteEndNotify ()
                | GCNotificationStatus.Canceled ->
                    printfn "GC Notification cancelled."
                    broken <- true
                | _ ->
                    // Could be a time out.
                    printfn "GC Notification not applicable."
                    broken <- true
            | GCNotificationStatus.Canceled ->
                printfn "GC Notification cancelled."
                broken <- true
            | _ ->
                // This can occur if a timeout period
                // is specified for WaitForFullGCApproach(Timeout)
                // or WaitForFullGCComplete(Timeout)
                // and the time out period has elapsed.
                printfn "GC Notification not applicable."
                broken <- true

        Thread.Sleep 500
        // FinalExit is set to true right before
        // the main thread cancelled notification.
        if finalExit then broken <- true



try
    // Register for a notification.
    GC.RegisterForFullGCNotification(10, 10)
    printfn "Registered for GC notification."

    checkForNotify <- true
    bAllocate <- true

    // Start a thread using WaitForFullGCProc.
    let thWaitForFullGC = Thread(ThreadStart waitForFullGCProc)
    thWaitForFullGC.Start()

    // While the thread is checking for notifications in
    // WaitForFullGCProc, create objects to simulate a server workload.
    try
        let mutable lastCollCount = 0
        let mutable newCollCount = 0

        let mutable broken = false

        while not broken do
            if bAllocate then
                load.Add(Array.zeroCreate<byte> 1000)
                newCollCount <- GC.CollectionCount 2

                if newCollCount <> lastCollCount then
                    // Show collection count when it increases:
                    printfn $"Gen 2 collection count: {GC.CollectionCount(2)}"
                    lastCollCount <- newCollCount
                // For ending the example (arbitrary).
                if newCollCount = 500 then
                    finalExit <- true
                    checkForNotify <- false
                    broken <- true
    with :? OutOfMemoryException -> printfn "Out of memory."

    finalExit <- true
    checkForNotify <- false
    GC.CancelFullGCNotification()
with :? InvalidOperationException as invalidOp ->
    printfn $"GC Notifications are not supported while concurrent GC is enabled.\n{invalidOp.Message}"
Imports System.Collections.Generic
Imports System.Threading

Class Program
    ' Variables for continual checking in the
    ' While loop in the WaitForFullGcProc method.
    Private Shared checkForNotify As Boolean = False

    ' Variable for suspending work 
    ' (such as servicing allocated server requests)
    ' after a notification is received and then 
    ' resuming allocation after inducing a garbage collection.
    Private Shared bAllocate As Boolean = False

    ' Variable for ending the example.
    Private Shared finalExit As Boolean = False

    ' Collection for objects that  
    ' simulate the server request workload.
    Private Shared load As New List(Of Byte())


    Public Shared Sub Main(ByVal args() As String)
        Try
            ' Register for a notification. 
            GC.RegisterForFullGCNotification(10, 10)
            Console.WriteLine("Registered for GC notification.")

            bAllocate = True
            checkForNotify = True

            ' Start a thread using WaitForFullGCProc.
            Dim thWaitForFullGC As Thread = _
                New Thread(New ThreadStart(AddressOf WaitForFullGCProc))
            thWaitForFullGC.Start()

            ' While the thread is checking for notifications in
            ' WaitForFullGCProc, create objects to simulate a server workload.
            Try
                Dim lastCollCount As Integer = 0
                Dim newCollCount As Integer = 0
                
                
                While (True)
                    If bAllocate = True Then

                        load.Add(New Byte(1000) {})
                        newCollCount = GC.CollectionCount(2)
                        If (newCollCount <> lastCollCount) Then
                            ' Show collection count when it increases:
                            Console.WriteLine("Gen 2 collection count: {0}", _
                                              GC.CollectionCount(2).ToString)
                            lastCollCount = newCollCount
                        End If

                        ' For ending the example (arbitrary).
                        If newCollCount = 500 Then
                            finalExit = True
                            checkForNotify = False
                            bAllocate = False
                            Exit While
                        End If

                    End If
                End While
                
            Catch outofMem As OutOfMemoryException
                Console.WriteLine("Out of memory.")
            End Try

            finalExit = True
            checkForNotify = False
            GC.CancelFullGCNotification()

        Catch invalidOp As InvalidOperationException
            Console.WriteLine("GC Notifications are not supported while concurrent GC is enabled." _
                              & vbLf & invalidOp.Message)
        End Try
    End Sub

    Public Shared Sub OnFullGCApproachNotify()
        Console.WriteLine("Redirecting requests.")

        ' Method that tells the request queuing  
        ' server to not direct requests to this server. 
        RedirectRequests()

        ' Method that provides time to 
        ' finish processing pending requests. 
        FinishExistingRequests()

        ' This is a good time to induce a GC collection
        ' because the runtime will induce a ful GC soon.
        ' To be very careful, you can check precede with a
        ' check of the GC.GCCollectionCount to make sure
        ' a full GC did not already occur since last notified.
        GC.Collect()
        Console.WriteLine("Induced a collection.")
    End Sub

    Public Shared Sub OnFullGCCompleteEndNotify()
        ' Method that informs the request queuing server
        ' that this server is ready to accept requests again.
        AcceptRequests()
        Console.WriteLine("Accepting requests again.")
    End Sub

    Public Shared Sub WaitForFullGCProc()

        While True
            ' CheckForNotify is set to true and false in Main.

            While checkForNotify
                ' Check for a notification of an approaching collection.
                Dim s As GCNotificationStatus = GC.WaitForFullGCApproach
                If (s = GCNotificationStatus.Succeeded) Then
                    Console.WriteLine("GC Notification raised.")
                    OnFullGCApproachNotify()
                ElseIf (s = GCNotificationStatus.Canceled) Then
                    Console.WriteLine("GC Notification cancelled.")
                    Exit While
                Else
                    ' This can occur if a timeout period
                    ' is specified for WaitForFullGCApproach(Timeout) 
                    ' or WaitForFullGCComplete(Timeout)  
                    ' and the time out period has elapsed. 
                    Console.WriteLine("GC Notification not applicable.")
                    Exit While
                End If

                ' Check for a notification of a completed collection.
                s = GC.WaitForFullGCComplete
                If (s = GCNotificationStatus.Succeeded) Then
                    Console.WriteLine("GC Notifiction raised.")
                    OnFullGCCompleteEndNotify()
                ElseIf (s = GCNotificationStatus.Canceled) Then
                    Console.WriteLine("GC Notification cancelled.")
                    Exit While
                Else
                    ' Could be a time out.
                    Console.WriteLine("GC Notification not applicable.")
                    Exit While
                End If

            End While
            Thread.Sleep(500)
            ' FinalExit is set to true right before  
            ' the main thread cancelled notification.
            If finalExit Then
                Exit While
            End If

        End While
    End Sub

    Private Shared Sub RedirectRequests()
        ' Code that sends requests
        ' to other servers.

        ' Suspend work.
        bAllocate = False
    End Sub

    Private Shared Sub FinishExistingRequests()
        ' Code that waits a period of time
        ' for pending requests to finish.

        ' Clear the simulated workload.
        load.Clear()

    End Sub

    Private Shared Sub AcceptRequests()
        ' Code that resumes processing
        ' requests on this server.

        ' Resume work.
        bAllocate = True
    End Sub
End Class

備註

對於每一代,垃圾回收器會設定該世代的分配門檻。 當分配大小超過此門檻時,該世代會觸發垃圾回收。 例如,若第二代的門檻為 20MB(意即 20MB 能存活於第一代並升級為第二代),且超過 20MB 已存活第一代並被觸發進入第二代,則下一次垃圾回收將嘗試作為第二代收集。 同樣地,如果大型物件堆(LOH)的門檻是 20MB,且你的應用程式分配了超過 20MB 的大物件,下一次垃圾回收也會嘗試作為第二代回收(因為 LOH 只在第二代垃圾回收中被收集)。

maxGenerationThreshold和 largeObjectHeapThreshold 閾值控制你在完全垃圾回收發生前收到通知的時間。 門檻越高,通知到下一次完整垃圾回收之間能進行的分配越多。

如果你遇到在公共語言執行時進行完整垃圾回收會不利於應用程式效能的情況,你可以要求在執行環境即將進行完整垃圾回收時收到通知,並在條件仍有利時,自己用該 Collect 方法誘導一個收集來繞過該收集。 除了自行更改垃圾回收排程外,完整的 GC 通知對於以下情境也很有幫助:

  • 你監控完整的垃圾回收即將來臨,當收到通知時,你會減少即時資料大小(例如釋放部分快取條目)。 因此,當垃圾回收發生時,它能夠回收更多記憶體。

  • 你監控完整的垃圾回收完成,以便收集統計數據。 例如,你可能想在 GC 完成時測量堆積的大小,這樣你就能知道活躍資料的大小。 (完成 GC 後,堆積大小降至最小。)

關於完整垃圾回收的更多資訊,請參閱垃圾 回收通知。

當您註冊垃圾回收通知時,您可以收到完整垃圾回收即將到來及完成的通知。 這種模式類似作業系統監控記憶體不足通知的方式。

請使用以下指引來指定 maxGenerationThreshold 和 largeObjectHeapThreshold 參數:

  • 閾值越大,通知與完整垃圾回收之間的分配越多。

    較大的閾值則能讓執行時有更多機會檢查即將到來的集合。 這會增加你被通知的可能性。 不過,你不應該把門檻設得太高,因為這樣會導致在執行時間誘發下一個集合前,分配的數量會增加。

    當你在通知時自己誘導集合,使用高閾值時,回收的物件數量比執行時下一個集合回收的要少。

  • 閾值越小,通知與完整垃圾回收之間的分配越少。

適用於

另請參閱