GC.RegisterForFullGCNotification(Int32, Int32) Método
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
Especifica que uma notificação de coleta de lixo deve ser gerada quando as condições favorecerem a coleta de lixo completa e quando a coleção tiver sido concluída.
public:
static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold);
public static void RegisterForFullGCNotification (int maxGenerationThreshold, int largeObjectHeapThreshold);
[System.Security.SecurityCritical]
public static void RegisterForFullGCNotification (int maxGenerationThreshold, int largeObjectHeapThreshold);
static member RegisterForFullGCNotification : int * int -> unit
[<System.Security.SecurityCritical>]
static member RegisterForFullGCNotification : int * int -> unit
Public Shared Sub RegisterForFullGCNotification (maxGenerationThreshold As Integer, largeObjectHeapThreshold As Integer)
Parâmetros
- maxGenerationThreshold
- Int32
Um número entre 1 e 99 que especifica quando a notificação deve ser gerada com base nos objetos alocados na geração 2.
- largeObjectHeapThreshold
- Int32
Um número entre 1 e 99 que especifica quando a notificação deve ser gerada com base nos objetos alocados no heap de objetos grandes.
- Atributos
Exceções
maxGenerationThreshold
ou largeObjectHeapThreshold
não está entre 1 e 99.
Este membro não está disponível quando a coleta de lixo simultânea está habilitada. Consulte a configuração de runtime <gcConcurrent> para obter informações sobre como desabilitar a coleta de lixo simultânea.
Exemplos
O exemplo a seguir mostra como registrar uma notificação de coleta de lixo e iniciar um thread para monitorar o status da notificação de coleta de lixo. Este exemplo de código faz parte de um exemplo maior fornecido para o tópico Notificações de Coleta de Lixo .
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;
}
}
}
open System
open System.Threading
// Variable for continual checking in the
// While loop in the WaitForFullGCProc method.
let mutable checkForNotify = false
// Variable for suspending work
// (such servicing allocated server requests)
// after a notification is received and then
// resuming allocation after inducing a garbage collection.
let mutable bAllocate = false
// Variable for ending the example.
let mutable finalExit = false
// Collection for objects that simulate the server request workload.
let load = ResizeArray<byte []>()
let redirectRequests () =
// Code that sends requests
// to other servers.
// Suspend work.
bAllocate <- false
let finishExistingRequests () =
// Code that waits a period of time
// for pending requests to finish.
// Clear the simulated workload.
load.Clear()
let acceptRequests () =
// Code that resumes processing
// requests on this server.
// Resume work.
bAllocate <- true
let onFullGCApproachNotify () =
printfn "Redirecting requests."
// Method that tells the request queuing
// server to not direct requests to this server.
redirectRequests ()
// Method that provides time to
// finish processing pending requests.
finishExistingRequests ()
// This is a good time to induce a GC collection
// because the runtime will induce a full GC soon.
// To be very careful, you can check precede with a
// check of the GC.GCCollectionCount to make sure
// a full GC did not already occur since last notified.
GC.Collect()
printfn "Induced a collection."
let onFullGCCompleteEndNotify () =
// Method that informs the request queuing server
// that this server is ready to accept requests again.
acceptRequests ()
printfn "Accepting requests again."
let waitForFullGCProc () =
let mutable broken = false
while not broken do
let mutable broken = false
// CheckForNotify is set to true and false in Main.
while checkForNotify && not broken do
// Check for a notification of an approaching collection.
match GC.WaitForFullGCApproach() with
| GCNotificationStatus.Succeeded ->
printfn "GC Notification raised."
onFullGCApproachNotify ()
// Check for a notification of a completed collection.
match GC.WaitForFullGCComplete() with
| GCNotificationStatus.Succeeded ->
printfn "GC Notification raised."
onFullGCCompleteEndNotify ()
| GCNotificationStatus.Canceled ->
printfn "GC Notification cancelled."
broken <- true
| _ ->
// Could be a time out.
printfn "GC Notification not applicable."
broken <- true
| GCNotificationStatus.Canceled ->
printfn "GC Notification cancelled."
broken <- true
| _ ->
// This can occur if a timeout period
// is specified for WaitForFullGCApproach(Timeout)
// or WaitForFullGCComplete(Timeout)
// and the time out period has elapsed.
printfn "GC Notification not applicable."
broken <- true
Thread.Sleep 500
// FinalExit is set to true right before
// the main thread cancelled notification.
if finalExit then broken <- true
try
// Register for a notification.
GC.RegisterForFullGCNotification(10, 10)
printfn "Registered for GC notification."
checkForNotify <- true
bAllocate <- true
// Start a thread using WaitForFullGCProc.
let thWaitForFullGC = Thread(ThreadStart waitForFullGCProc)
thWaitForFullGC.Start()
// While the thread is checking for notifications in
// WaitForFullGCProc, create objects to simulate a server workload.
try
let mutable lastCollCount = 0
let mutable newCollCount = 0
let mutable broken = false
while not broken do
if bAllocate then
load.Add(Array.zeroCreate<byte> 1000)
newCollCount <- GC.CollectionCount 2
if newCollCount <> lastCollCount then
// Show collection count when it increases:
printfn $"Gen 2 collection count: {GC.CollectionCount(2)}"
lastCollCount <- newCollCount
// For ending the example (arbitrary).
if newCollCount = 500 then
finalExit <- true
checkForNotify <- false
broken <- true
with :? OutOfMemoryException -> printfn "Out of memory."
finalExit <- true
checkForNotify <- false
GC.CancelFullGCNotification()
with :? InvalidOperationException as invalidOp ->
printfn $"GC Notifications are not supported while concurrent GC is enabled.\n{invalidOp.Message}"
Imports System.Collections.Generic
Imports System.Threading
Class Program
' Variables for continual checking in the
' While loop in the WaitForFullGcProc method.
Private Shared checkForNotify As Boolean = False
' Variable for suspending work
' (such as servicing allocated server requests)
' after a notification is received and then
' resuming allocation after inducing a garbage collection.
Private Shared bAllocate As Boolean = False
' Variable for ending the example.
Private Shared finalExit As Boolean = False
' Collection for objects that
' simulate the server request workload.
Private Shared load As New List(Of Byte())
Public Shared Sub Main(ByVal args() As String)
Try
' Register for a notification.
GC.RegisterForFullGCNotification(10, 10)
Console.WriteLine("Registered for GC notification.")
bAllocate = True
checkForNotify = True
' Start a thread using WaitForFullGCProc.
Dim thWaitForFullGC As Thread = _
New Thread(New ThreadStart(AddressOf WaitForFullGCProc))
thWaitForFullGC.Start()
' While the thread is checking for notifications in
' WaitForFullGCProc, create objects to simulate a server workload.
Try
Dim lastCollCount As Integer = 0
Dim newCollCount As Integer = 0
While (True)
If bAllocate = True Then
load.Add(New Byte(1000) {})
newCollCount = GC.CollectionCount(2)
If (newCollCount <> lastCollCount) Then
' Show collection count when it increases:
Console.WriteLine("Gen 2 collection count: {0}", _
GC.CollectionCount(2).ToString)
lastCollCount = newCollCount
End If
' For ending the example (arbitrary).
If newCollCount = 500 Then
finalExit = True
checkForNotify = False
bAllocate = False
Exit While
End If
End If
End While
Catch outofMem As OutOfMemoryException
Console.WriteLine("Out of memory.")
End Try
finalExit = True
checkForNotify = False
GC.CancelFullGCNotification()
Catch invalidOp As InvalidOperationException
Console.WriteLine("GC Notifications are not supported while concurrent GC is enabled." _
& vbLf & invalidOp.Message)
End Try
End Sub
Public Shared Sub OnFullGCApproachNotify()
Console.WriteLine("Redirecting requests.")
' Method that tells the request queuing
' server to not direct requests to this server.
RedirectRequests()
' Method that provides time to
' finish processing pending requests.
FinishExistingRequests()
' This is a good time to induce a GC collection
' because the runtime will induce a ful GC soon.
' To be very careful, you can check precede with a
' check of the GC.GCCollectionCount to make sure
' a full GC did not already occur since last notified.
GC.Collect()
Console.WriteLine("Induced a collection.")
End Sub
Public Shared Sub OnFullGCCompleteEndNotify()
' Method that informs the request queuing server
' that this server is ready to accept requests again.
AcceptRequests()
Console.WriteLine("Accepting requests again.")
End Sub
Public Shared Sub WaitForFullGCProc()
While True
' CheckForNotify is set to true and false in Main.
While checkForNotify
' Check for a notification of an approaching collection.
Dim s As GCNotificationStatus = GC.WaitForFullGCApproach
If (s = GCNotificationStatus.Succeeded) Then
Console.WriteLine("GC Notification raised.")
OnFullGCApproachNotify()
ElseIf (s = GCNotificationStatus.Canceled) Then
Console.WriteLine("GC Notification cancelled.")
Exit While
Else
' This can occur if a timeout period
' is specified for WaitForFullGCApproach(Timeout)
' or WaitForFullGCComplete(Timeout)
' and the time out period has elapsed.
Console.WriteLine("GC Notification not applicable.")
Exit While
End If
' Check for a notification of a completed collection.
s = GC.WaitForFullGCComplete
If (s = GCNotificationStatus.Succeeded) Then
Console.WriteLine("GC Notifiction raised.")
OnFullGCCompleteEndNotify()
ElseIf (s = GCNotificationStatus.Canceled) Then
Console.WriteLine("GC Notification cancelled.")
Exit While
Else
' Could be a time out.
Console.WriteLine("GC Notification not applicable.")
Exit While
End If
End While
Thread.Sleep(500)
' FinalExit is set to true right before
' the main thread cancelled notification.
If finalExit Then
Exit While
End If
End While
End Sub
Private Shared Sub RedirectRequests()
' Code that sends requests
' to other servers.
' Suspend work.
bAllocate = False
End Sub
Private Shared Sub FinishExistingRequests()
' Code that waits a period of time
' for pending requests to finish.
' Clear the simulated workload.
load.Clear()
End Sub
Private Shared Sub AcceptRequests()
' Code that resumes processing
' requests on this server.
' Resume work.
bAllocate = True
End Sub
End Class
Comentários
Para cada geração, o coletor de lixo define um limite para alocações nessa geração. Quando o tamanho das alocações excede esse limite, uma coleta de lixo é disparada nessa geração. Por exemplo, se o limite da geração 2 for de 20 MB (o que significa que 20 MB sobrevive a coletas de geração 1 e é promovido para a geração 2), e mais de 20 MB sobreviveu à geração 1 e é solicitado para a geração 2, a próxima coleta de lixo será tentada como uma coleta de geração 2. Da mesma forma, se o limite de LOH (heap de objeto grande) for de 20 MB e seu aplicativo tiver alocado mais de 20 MB de objetos grandes, a próxima coleta de lixo também será tentada como uma coleta de geração 2 (uma vez que o LOH só é coletado em coletas de lixo gen2).
Os maxGenerationThreshold
limites e os limites largeObjectHeapThreshold
controlam com antecedência quanto você é notificado antes que uma coleta de lixo completa ocorra. Quanto maior o limite, mais alocações podem ocorrer entre a notificação e a próxima coleta completa de lixo.
Se você tiver situações em que uma coleta de lixo completa pelo common language runtime afetaria negativamente o desempenho do aplicativo, você poderá solicitar que seja notificado quando o runtime estiver prestes a fazer uma coleta completa de lixo e contornar essa coleta induzindo uma coleta por conta própria (usando o método) quando as Collect condições ainda estiverem favoráveis. Além de alterar a agenda de coleta de lixo por conta própria, a notificação completa do GC é útil nos seguintes cenários:
Você monitora a abordagem de uma coleta de lixo completa e, quando for notificado de que uma está se aproximando, reduz o tamanho dos dados dinâmicos (por exemplo, liberando algumas entradas de cache). Como resultado, quando a coleta de lixo ocorre, ela é capaz de recuperar mais memória.
Você monitora a conclusão de uma coleta de lixo completa para que possa coletar algumas estatísticas. Por exemplo, talvez você queira medir o tamanho do heap na conclusão do GC para saber o tamanho dos dados dinâmicos. (Depois de um GC completo, o heap está em seu menor tamanho.)
Para obter mais informações sobre o que representa uma coleta de lixo completa, consulte Notificações de Coleta de Lixo.
Ao se registrar para uma notificação de coleta de lixo, você poderá ser notificado quando uma coleta de lixo completa estiver se aproximando e quando ela for concluída. Esse padrão se assemelha a como o sistema operacional monitora notificações de memória baixa.
Use as seguintes diretrizes para especificar os parâmetros e largeObjectHeapThreshold
os maxGenerationThreshold
parâmetros:
Quanto maior o valor limite, mais alocações ocorrerão entre a notificação e a coleta completa de lixo.
Um valor de limite maior oferece mais oportunidades para o runtime verificar se há uma coleção se aproximando. Isso aumenta a probabilidade de você ser notificado. No entanto, você não deve definir o limite muito alto porque isso resulta em mais alocações antes que o runtime induza a próxima coleção.
Quando você induz uma coleção por conta própria após a notificação usando um valor limite alto, menos objetos são recuperados do que seriam recuperados pela próxima coleção do runtime.
Quanto menor o valor limite, menos alocações entre a notificação e a coleta de lixo completa.