Mis dos centavos en el método GC.Collect en C #

El método GC.Collect () ha sido durante mucho tiempo popular entre los desarrolladores de .Net. Sin embargo, pocos de nosotros sabemos cómo funciona realmente o si se necesita una llamada.

CLR (Common Language Runtime) adopta la recolección de basura como un mecanismo para limpiar los recursos consumidos por su aplicación. Tenga en cuenta que cuando crea objetos en .Net, se almacenan en el montón administrado, y cuando haya terminado de usarlos, no debe preocuparse por limpiarlos, el tiempo de ejecución lo haría por usted.

El CLR organiza el montón administrado en generaciones. Las tres generaciones en las que se organiza el montón administrado son: Generación 0, Generación 1 y Generación 2. El GC es experto en recuperar la memoria ocupada por los objetos administrados. Sin embargo, debe seguir ciertas pautas para facilitar una recolección de basura más rápida a fin de mejorar el rendimiento de su aplicación.

¿Debo usar el método GC.Collect ()?

En primer lugar, ¿necesitas llamar a GC.Collect en el código de tu aplicación? La respuesta en la mayoría de los casos es no. Permítame ahora decirle qué hace este método y por qué debe abstenerse de llamar a este método en la mayoría de los casos.

Cuando realiza una llamada al método GC.Collect (), el tiempo de ejecución realiza un recorrido de la pila para determinar los objetos que son accesibles y los que no. También congela el hilo principal (y también los hilos secundarios que creó) de la aplicación. En otras palabras, cuando se llama al método GC.Collect (), el tiempo de ejecución realiza una recolección de basura de bloqueo de todas las generaciones.

Siempre preferiría no usar GC.Collect () a menos que haya una razón específica para usarlo. Un GC generalmente consta de las fases de marcado y barrido seguidas de una fase de compactación. El tiempo empleado por el tiempo de ejecución para realizar una GC puede convertirse en un cuello de botella, por lo tanto, utilícelo solo muy raramente y si realmente lo necesita. Rico Mariani afirma: "Considere llamar a GC.Collect () si acaba de ocurrir algún evento no recurrente y es muy probable que este evento haya causado la muerte de muchos objetos antiguos".

Usando el método GC.Collect ()

He aquí cómo puede invocar el método GC.Collect () en su código.

GC.Collect();

Tenga en cuenta que también puede recopilar objetos que pertenecen a una generación específica.

GC.Collect() - utilizado para recolectar objetos presentes en las generaciones 0, 1, 2

GC.Collect(0) - utilizado para recolectar objetos presentes en la generación 0

GC.Collect(1) - utilizado para recolectar objetos presentes en las generaciones 0 y

También puede determinar cuánta memoria se ha liberado haciendo una llamada al método GC.Collect (). Para hacer esto, puede aprovechar el método System.GC.GetTotalMemory () como se muestra en el fragmento de código a continuación.

//Write code to create some large objects here

Console.WriteLine("Total available memory before collection: {0:N0}", System.GC.GetTotalMemory(false));

System.GC.Collect();

Console.WriteLine("Total available memory collection: {0:N0}", System.GC.GetTotalMemory(true));

El método GC.GetGeneration () se puede utilizar para conocer la generación a la que pertenece un objeto. Consulte la lista de códigos que se proporciona a continuación.

static void Main(string[] args)

       {

           List obj = new List() { "Joydip", "Steve" };

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           System.GC.Collect();

           Console.WriteLine(System.GC.GetGeneration(obj));

           Console.Read();

       }

Cuando ejecuta el programa anterior, esto es lo que se imprime en la ventana de la consola.

0

1

2

Como puede ver, cada llamada al método GC.Collect () promueve el objeto "obj" a la siguiente generación superior. Esto se debe a que el objeto "obj" sobrevive a la recolección de basura en cada uno de los dos casos, es decir, no se recupera en ninguna de las dos llamadas realizadas al método GC.Collect ().

Puede forzar la recolección de basura para las tres generaciones o para una generación específica usando el método GC.Collect (). El método GC.Collect () está sobrecargado: puede llamarlo sin ningún parámetro o incluso pasando el número de generación que le gustaría que el recolector de basura recopile.

Tenga en cuenta que los objetos que tienen finalizadores (y si no se ha realizado una llamada al método SuppressFinalize) no se recopilarán cuando se realice una llamada al método GC.Collect (). Más bien, dichos objetos se colocarían en la cola de finalización. Si también desea recopilar esos objetos, deberá realizar una llamada al método GC.WaitForPendingFinalizers () para que esos objetos se limpien cuando se ejecute el siguiente ciclo de GC. En esencia, recuperar la memoria ocupada por objetos que tienen finalizadores implementados requiere dos pasadas, ya que dichos objetos se colocan en la cola de finalización en lugar de ser reclamados en la primera pasada cuando se ejecuta el recolector de basura.