Sdílet prostřednictvím


Oznámení pro kolekci paměti

Existují situace, kdy úplné uvolňování paměti (tj. kolekce 2. generace) modulu CLR (Common Language Runtime) může nepříznivě ovlivnit výkon. Může to být problém zejména u serverů, které zpracovávají velké objemy požadavků; v tomto případě může dlouhé uvolňování paměti způsobit vypršení časového limitu požadavku. Pokud chcete zabránit výskytu úplné kolekce během kritického období, můžete být upozorněni, že se blíží úplné uvolňování paměti, a pak proveďte akci pro přesměrování úlohy na jinou instanci serveru. Můžete také vyvolat kolekci sami za předpokladu, že aktuální instance serveru nemusí zpracovávat požadavky.

Metoda RegisterForFullGCNotification zaregistruje oznámení, které se má vyvolat, když modul runtime považuje za úplné uvolňování paměti. Toto oznámení má dvě části: když se blíží úplné uvolňování paměti a po dokončení úplného uvolňování paměti.

Upozorňující

<Pokud je povolen konfigurační prvek gcConcurrent>, WaitForFullGCComplete může se vrátit NotApplicable GCNotificationStatus, pokud úplné uvolňování paměti bylo provedeno jako GC na pozadí.

K určení, kdy bylo vyvolání oznámení, použijte metody WaitForFullGCApproach a WaitForFullGCComplete metody. Tyto metody se obvykle používají ve while smyčce k průběžnému získání GCNotificationStatus výčtu, který zobrazuje stav oznámení. Pokud je tato Succeededhodnota, můžete udělat toto:

  • V reakci na oznámení získané metodou WaitForFullGCApproach můžete úlohu přesměrovat a případně vyvolat kolekci sami.

  • V reakci na oznámení získané metodou WaitForFullGCComplete můžete zpřístupnit aktuální instanci serveru pro opětovné zpracování požadavků. Můžete také shromáždit informace. Můžete například použít metodu CollectionCount k zaznamenání počtu kolekcí.

Metody WaitForFullGCApproach a WaitForFullGCComplete metody jsou navrženy tak, aby spolupracovaly. Použití jedné bez druhé může vést k nedeterminátům výsledků.

Úplné uvolňování paměti

Modul runtime způsobí úplné uvolňování paměti, pokud platí některý z následujících scénářů:

  • Do generace 2 bylo povýšeno dostatek paměti, aby vznikla kolekce příští generace 2.

  • Dostatek paměti bylo povýšeno do haldy velkého objektu, aby způsobila kolekci příští generace 2.

  • Kolekce generace 1 je eskalována na kolekci generace 2 z důvodu jiných faktorů.

Prahové hodnoty, které zadáte v RegisterForFullGCNotification metodě, platí pro první dva scénáře. V prvním scénáři však nebudete vždy dostávat oznámení v době úměrné hodnotám prahových hodnot, které zadáte ze dvou důvodů:

  • Modul runtime nekontroluje přidělení jednotlivých malých objektů (z důvodů výkonu).

  • Pouze kolekce 1. generace podporují paměť do generace 2.

Třetí scénář také přispívá k nejistotě, kdy obdržíte oznámení. I když to není záruka, ukázalo se, že je užitečný způsob, jak zmírnit účinky inopportune úplné uvolňování paměti přesměrováním požadavků během této doby nebo vynucením kolekce sami, když to může být lépe uspokojené.

Parametry prahové hodnoty oznámení

Metoda RegisterForFullGCNotification má dva parametry pro zadání prahových hodnot objektů generace 2 a haldy velkého objektu. Při splnění těchto hodnot by mělo být vyvolána oznámení o uvolňování paměti. Následující tabulka popisuje tyto parametry.

Parametr Popis
maxGenerationThreshold Číslo mezi 1 a 99, které určuje, kdy má být oznámení vyvolána na základě objektů upřednostněných v generaci 2.
largeObjectHeapThreshold Číslo mezi 1 a 99, které určuje, kdy má být oznámení vyvolána na základě objektů, které jsou přiděleny v haldě velkého objektu.

Pokud zadáte hodnotu, která je příliš vysoká, zobrazí se oznámení s vysokou pravděpodobností, ale může to být příliš dlouhé období, než modul runtime způsobí kolekci. Pokud vyvoláte kolekci sami, můžete uvolnit více objektů, než by bylo možné uvolnit, pokud modul runtime způsobí kolekci.

Pokud zadáte hodnotu, která je příliš nízká, může modul runtime způsobit kolekci dříve, než jste měli dostatek času na oznámení.

Příklad

Popis

V následujícím příkladu je skupina serverů příchozích webových požadavků. Pro simulaci úlohy zpracování požadavků se do kolekce přidají List<T> pole bajtů. Každý server zaregistruje oznámení o uvolňování paměti a pak spustí vlákno metody WaitForFullGCProc uživatele, aby nepřetržitě monitoruje GCNotificationStatus výčet, který je vrácen jednotlivými metodami WaitForFullGCApproach a WaitForFullGCComplete metodami.

Metody WaitForFullGCApproach a WaitForFullGCComplete metody volají příslušné uživatelské metody pro zpracování událostí při vyvolání oznámení:

  • OnFullGCApproachNotify

    Tato metoda volá metodu RedirectRequests uživatele, která dává serveru řízení front požadavků pokyn, aby pozastavil odesílání požadavků na server. To se simuluje nastavením proměnné bAllocate na úrovni třídy tak false , aby se nepřidělily žádné další objekty.

    Dále se volá metoda uživatele, FinishExistingRequests která dokončí zpracování čekajících požadavků na server. Toto je simulované vymazáním List<T> kolekce.

    Nakonec se vyvolá uvolňování paměti, protože úloha je lehká.

  • OnFullGCCompleteNotify

    Tato metoda volá metodu AcceptRequests uživatele, aby obnovila přijímání požadavků, protože server již není náchylný k úplnému uvolňování paměti. Tato akce se simuluje nastavením bAllocate proměnné tak true , aby objekty mohly do kolekce pokračovat List<T> .

Následující kód obsahuje metodu Main příkladu.

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Threading;

namespace GCNotify
{
    ref class Program
    {
    private:
        // 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<array<Byte>^>^ load = gcnew List<array<Byte>^>();


    public:
        static void Main()
        {
            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 = gcnew Thread(gcnew 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(gcnew array<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.
                    s = GC::WaitForFullGCComplete();
                    if (s == GCNotificationStatus::Succeeded)
                    {
                        Console::WriteLine("GC Notification raised.");
                        OnFullGCCompleteEndNotify();
                    }
                    else if (s == 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;

        }

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

            // Clear the simulated workload.
            load->Clear();

        }

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

            // Resume work.
            bAllocate = true;
        }
    };
}

int main()
{
    GCNotify::Program::Main();
}
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);
    }
}
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 Notification 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

Následující kód obsahuje uživatelskou metodu WaitForFullGCProc , která obsahuje nepřetržitou smyčku while, která kontroluje oznámení uvolňování paměti.

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.
                s = GC::WaitForFullGCComplete();
                if (s == GCNotificationStatus::Succeeded)
                {
                    Console::WriteLine("GC Notification raised.");
                    OnFullGCCompleteEndNotify();
                }
                else if (s == 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;
            }
        }
    }
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;
        }
    }
}
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 Notification 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

Následující kód obsahuje metodu OnFullGCApproachNotify volanou z

WaitForFullGCProc metoda.

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 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 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

Následující kód obsahuje metodu OnFullGCApproachComplete volanou z

WaitForFullGCProc metoda.

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 OnFullGCCompleteEndNotify()
{
    // Method that informs the request queuing server
    // that this server is ready to accept requests again.
    AcceptRequests();
    Console.WriteLine("Accepting requests again.");
}
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

Následující kód obsahuje uživatelské metody, které jsou volána z těchto OnFullGCApproachNotify metod a OnFullGCCompleteNotify metod. Metody uživatele přesměrovávají požadavky, dokončí stávající požadavky a po dokončení úplné uvolňování paměti obnoví požadavky.

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

        // Suspend work.
        bAllocate = false;

    }

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

        // Clear the simulated workload.
        load->Clear();

    }

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

        // Resume work.
        bAllocate = true;
    }
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;
}
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

Celý vzorový kód je následující:

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Threading;

namespace GCNotify
{
    ref class Program
    {
    private:
        // 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<array<Byte>^>^ load = gcnew List<array<Byte>^>();


    public:
        static void Main()
        {
            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 = gcnew Thread(gcnew 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(gcnew array<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.
                    s = GC::WaitForFullGCComplete();
                    if (s == GCNotificationStatus::Succeeded)
                    {
                        Console::WriteLine("GC Notification raised.");
                        OnFullGCCompleteEndNotify();
                    }
                    else if (s == 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;

        }

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

            // Clear the simulated workload.
            load->Clear();

        }

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

            // Resume work.
            bAllocate = true;
        }
    };
}

int main()
{
    GCNotify::Program::Main();
}
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;
        }
    }
}
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 Notification 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

Viz také