가비지 컬렉션 알림Garbage Collection Notifications

공용 언어 런타임에서 전체 가비지 컬렉션(즉, 2세대 컬렉션)을 실행하면 성능이 저하될 수 있는 경우가 있습니다.There are situations in which a full garbage collection (that is, a generation 2 collection) by the common language runtime may adversely affect performance. 이는 대량의 요청을 처리하는 서버에서 특히 문제가 될 수 있습니다. 이 경우 장기적인 가비지 수집으로 인해 요청 시간이 초과될 수 있습니다. 중요 기간에 전체 수집이 발생하지 않도록 하기 위해 전체 가비지 수집에 근접하고 있다는 알림을 받을 수 있습니다. 그러면 워크로드를 다른 서버 인스턴스로 리디렉션하는 조치를 취할 수 있습니다.This can be an issue particularly with servers that process large volumes of requests; in this case, a long garbage collection can cause a request time-out. To prevent a full collection from occurring during a critical period, you can be notified that a full garbage collection is approaching and then take action to redirect the workload to another server instance. 또한 현재 서버 인스턴스가 요청을 처리하지 않아도 되는 경우 직접 수집을 유도할 수도 있습니다.You can also induce a collection yourself, provided that the current server instance does not need to process requests.

RegisterForFullGCNotification 메서드는 런타임에서 전체 가비지 수집에 근접하고 있음을 감지할 때 발생되는 알림에 등록합니다.The RegisterForFullGCNotification method registers for a notification to be raised when the runtime senses that a full garbage collection is approaching. 이 알림에는 두 부분이 있습니다. 즉, 알림은 전체 가비지 수집에 근접하고 있을 때와 전체 가비지 수집이 완료되었을 때 발생할 수 있습니다.There are two parts to this notification: when the full garbage collection is approaching and when the full garbage collection has completed.

경고

차단 가비지 컬렉션만 알림을 발생시킵니다.Only blocking garbage collections raise notifications. <gcConcurrent> 구성 요소를 사용하면 백그라운드 가비지 수집은 알림을 발생시키지 않습니다.When the <gcConcurrent> configuration element is enabled, background garbage collections will not raise notifications.

알림이 발생한 시기를 확인하려면 WaitForFullGCApproachWaitForFullGCComplete 메서드를 사용합니다.To determine when a notification has been raised, use the WaitForFullGCApproach and WaitForFullGCComplete methods. 일반적으로 while 루프에 이러한 메서드를 사용하면 알림 상태를 표시하는 GCNotificationStatus 열거형을 계속해서 가져올 수 있습니다.Typically, you use these methods in a while loop to continually obtain a GCNotificationStatus enumeration that shows the status of the notification. 해당 값이 Succeeded인 경우 다음을 수행할 수 있습니다.If that value is Succeeded, you can do the following:

  • WaitForFullGCApproach 메서드를 사용하여 받은 알림에 대한 대응으로, 워크로드를 리디렉션하고 직접 수집을 유도할 수도 있습니다.In response to a notification obtained with the WaitForFullGCApproach method, you can redirect the workload and possibly induce a collection yourself.

  • WaitForFullGCComplete 메서드를 사용하여 받은 알림에 대한 대응으로, 현재 서버 인스턴스에서 요청을 다시 처리할 수 있게 설정할 수 있습니다.In response to a notification obtained with the WaitForFullGCComplete method, you can make the current server instance available to process requests again. 또한 정보도 수집할 수 있습니다.You can also gather information. 예를 들어 CollectionCount 메서드를 사용하여 컬렉션 수를 기록할 수 있습니다.For example, you can use the CollectionCount method to record the number of collections.

WaitForFullGCApproachWaitForFullGCComplete 메서드는 함께 작동하도록 설계되었습니다.The WaitForFullGCApproach and the WaitForFullGCComplete methods are designed to work together. 두 메서드를 함께 사용하지 않고 하나만 사용하면 불확실한 결과를 얻을 수 있습니다.Using one without the other can produce indeterminate results.

전체 가비지 수집Full Garbage Collection

다음 시나리오 중 하나에 해당하는 경우 런타임은 전체 가비지 수집을 발생시킵니다.The runtime causes a full garbage collection when any of the following scenarios are true:

  • 그다음 세대 2 컬렉션을 일으키기에 충분한 메모리가 세대 2로 승격된 경우.Enough memory has been promoted into generation 2 to cause the next generation 2 collection.

  • 그다음 세대 2 컬렉션을 일으키기에 충분한 메모리가 대형 개체 힙으로 승격된 경우.Enough memory has been promoted into the large object heap to cause the next generation 2 collection.

  • 세대 1의 컬렉션이 다른 요인으로 인해 세대 2의 컬렉션으로 에스컬레이션된 경우A collection of generation 1 is escalated to a collection of generation 2 due to other factors.

RegisterForFullGCNotification 메서드에서 지정한 임계값은 처음 두 시나리오에 적용됩니다.The thresholds you specify in the RegisterForFullGCNotification method apply to the first two scenarios. 그러나 첫 번째 시나리오에서는 다음과 같은 두 가지 이유로 지정된 임계값에 비례한 시간에 알림을 항상 받지는 못합니다.However, in the first scenario you will not always receive the notification at the time proportional to the threshold values you specify for two reasons:

  • 런타임이 성능상의 이유로 각각의 소형 개체 할당을 확인하지 않습니다.The runtime does not check each small object allocation (for performance reasons).

  • 세대 1 컬렉션만 메모리 수준이 세대 2로 올라갑니다.Only generation 1 collections promote memory into generation 2.

또한 세 번째 시나리오는 알림을 받을 수 있는 시기를 불확실하게 하는 원인이 됩니다.The third scenario also contributes to the uncertainty of when you will receive the notification. 따라서 보장할 수는 없지만, 이 시간 동안 요청을 리디렉션하거나 더 잘 수용할 수 있을 때 직접 수집을 유도함으로써 부적절한 시기의 전체 가비지 수집으로 인한 영향을 완화하는 것이 유용한 방법임은 명백합니다.Although this is not a guarantee, it does prove to be a useful way to mitigate the effects of an inopportune full garbage collection by redirecting the requests during this time or inducing the collection yourself when it can be better accommodated.

알림 임계값 매개 변수Notification Threshold Parameters

RegisterForFullGCNotification 메서드에는 세대 2 개체 및 대형 개체 힙의 임계값을 지정하는 두 개의 매개 변수가 있습니다.The RegisterForFullGCNotification method has two parameters to specify the threshold values of the generation 2 objects and the large object heap. 이러한 값이 충족되면 가비지 수집 알림이 발생되어야 합니다.When those values are met, a garbage collection notification should be raised. 다음 표에서는 이러한 매개 변수에 대해 설명합니다.The following table describes these parameters.

매개 변수Parameter 설명Description
maxGenerationThreshold 세대 2에서 수준이 상승된 개체에 따라 알림을 발생시킬 시점을 지정하는 1에서 99 사이의 숫자입니다.A number between 1 and 99 that specifies when the notification should be raised based on the objects promoted in generation 2.
largeObjectHeapThreshold 대형 개체 힙에 할당되는 개체에 따라 알림을 발생시킬 시점을 지정하는 1에서 99 사이의 숫자입니다.A number between 1 and 99 that specifies when the notification should be raised based on the objects that are allocated in the large object heap.

너무 높은 값을 지정하는 경우 알림을 받을 확률은 높아지지만 런타임에서 수집을 일으킬 때까지 너무 오래 대기할 수 있습니다.If you specify a value that is too high, there is a high probability that you will receive a notification, but it could be too long a period to wait before the runtime causes a collection. 직접 수집을 유도하는 경우 런타임에서 수집을 일으킬 때 회수하는 것보다 더 많은 개체를 회수할 수 있습니다.If you induce a collection yourself, you may reclaim more objects than would be reclaimed if the runtime causes the collection.

너무 낮은 값을 지정하는 경우 알림을 받기에 충분한 시간이 경과하기도 전에 런타임이 수집을 일으킬 수 있습니다.If you specify a value that is too low, the runtime may cause the collection before you have had sufficient time to be notified.

Example

설명Description

다음 예제에서 서버 그룹이 들어오는 웹 요청을 처리합니다.In the following example, a group of servers service incoming Web requests. 요청 처리의 워크로드를 시뮬레이트하기 위해 바이트 배열을 List<T> 컬렉션에 추가합니다.To simulate the workload of processing requests, byte arrays are added to a List<T> collection. 각 서버는 가비지 수집 알림에 등록한 후 WaitForFullGCProc 사용자 메서드의 스레드를 시작하여 WaitForFullGCApproachWaitForFullGCComplete 메서드에서 반환하는 GCNotificationStatus 열거형을 지속적으로 모니터링합니다.Each server registers for a garbage collection notification and then starts a thread on the WaitForFullGCProc user method to continuously monitor the GCNotificationStatus enumeration that is returned by the WaitForFullGCApproach and the WaitForFullGCComplete methods.

WaitForFullGCApproachWaitForFullGCComplete 메서드는 알림이 발생할 때 다음과 같은 각각의 이벤트 처리 사용자 메서드를 호출합니다.The WaitForFullGCApproach and the WaitForFullGCComplete methods call their respective event-handling user methods when a notification is raised:

  • OnFullGCApproachNotify

    이 메서드는 RedirectRequests 사용자 메서드를 호출하여, 서버로의 요청 전송을 일시 중단하도록 요청 큐 서버에 지시합니다.This method calls the RedirectRequests user method, which instructs the request queuing server to suspend sending requests to the server. 이는 더 이상 개체가 할당되지 않도록 클래스 수준 변수 bAllocatefalse로 설정하여 시뮬레이트됩니다.This is simulated by setting the class-level variable bAllocate to false so that no more objects are allocated.

    다음으로, 보류 중인 서버 요청에 대한 처리를 완료하기 위해 FinishExistingRequests 사용자 메서드를 호출합니다.Next, the FinishExistingRequests user method is called to finish processing the pending server requests. 이는 List<T> 컬렉션을 지움으로써 시뮬레이트됩니다.This is simulated by clearing the List<T> collection.

    마지막으로 워크로드가 가벼우므로 가비지 수집을 유도합니다.Finally, a garbage collection is induced because the workload is light.

  • OnFullGCCompleteNotify

    서버가 전체 가비지 수집에 더 이상 취약하지 않으므로 이 메서드는 사용자 메서드 AcceptRequests를 호출하여 요청 수락을 다시 시작합니다.This method calls the user method AcceptRequests to resume accepting requests because the server is no longer susceptible to a full garbage collection. 이 작업은 개체를 List<T> 컬렉션에 추가하는 것을 다시 시작할 수 있도록 bAllocate 변수를 true로 설정하여 시뮬레이트됩니다.This action is simulated by setting the bAllocate variable to true so that objects can resume being added to the List<T> collection.

다음 코드에는 예제의 Main 메서드가 포함되어 있습니다.The following code contains the Main method of the example.

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

다음 코드에는 가비지 수집 알림을 확인하기 위한 연속 while 루프가 들어 있는 WaitForFullGCProc 사용자 메서드가 포함되어 있습니다.The following code contains the WaitForFullGCProc user method, that contains a continuous while loop to check for garbage collection notifications.

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

다음 코드에는 다음에서 호출되는 OnFullGCApproachNotify 메서드가 포함되어 있습니다.The following code contains the OnFullGCApproachNotify method as called from the

WaitForFullGCProc 메서드를 호출하여 생성됩니다.WaitForFullGCProc method.

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

다음 코드에는 다음에서 호출되는 OnFullGCApproachComplete 메서드가 포함되어 있습니다.The following code contains the OnFullGCApproachComplete method as called from the

WaitForFullGCProc 메서드를 호출하여 생성됩니다.WaitForFullGCProc method.

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

다음 코드에는 OnFullGCApproachNotifyOnFullGCCompleteNotify 메서드에서 호출되는 사용자 메서드가 포함되어 있습니다.The following code contains the user methods that are called from the OnFullGCApproachNotify and OnFullGCCompleteNotify methods. 사용자 메서드는 요청을 리디렉션하고, 기존 요청을 완료한 다음, 전체 가비지 수집이 발생한 이후에 요청을 다시 시작합니다.The user methods redirect requests, finish existing requests, and then resume requests after a full garbage collection has occurred.

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

전체 코드 샘플은 다음과 같습니다.The entire code sample is as follows:

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

참고 항목See also