una todas tarjeta suscripciones suscripcion play paginas organizejobs las eliminar dar credito como celular cancelar baja c# .net events garbage-collection

c# - todas - ¿Debo eliminar las suscripciones a eventos de los objetos antes de que sean huérfanos?



como eliminar suscripciones de paginas (3)

Si mi software tiene dos instancias de objeto, una de ellas está suscrita a los eventos de la otra. ¿Debo cancelar la suscripción entre ellos antes de que sean huérfanos para que el recolector de basura los limpie? ¿O hay alguna otra razón por la que debería borrar las relaciones del evento? ¿Qué pasa si el suscrito al objeto es huérfano pero el suscriptor no lo es, o viceversa?


La suscripción a un evento da como resultado una fuerte referencia al suscriptor. Esto se debe a que, bajo las cubiertas, los eventos son delegados, y los delegados a los métodos de instancia son una combinación de la referencia del objeto y el método real. Si no se da de baja, el editor continuará manteniendo las referencias, y los objetos suscritos nunca se volverán verdaderamente huérfanos (y GC) siempre que el editor esté activo.

Lo contrario no es verdadero, es decir, el objeto suscrito no tiene ninguna referencia al editor.


Solo necesita desenganchar eventos si el objeto que expone los eventos es de larga duración, pero el objeto que enganchó el evento sería de corta duración (y obtendría la basura recogida con bastante rapidez).

En este caso, si no se desengancha, se producirá lo que equivale a una pérdida de memoria, ya que su objeto efímero no podrá ser GCed, ya que el evento en el objeto de larga duración tiene un delegado, que contiene una referencia a el objeto efímero. Como ese delegado aún hace referencia al objeto efímero, no se puede recolectar basura.

Los eventos estáticos duran mucho tiempo, por definición, viven hasta que el programa finaliza. Si conecta un evento estático, definitivamente debe desengancharlo cuando haya terminado.

Si ambos objetos están a punto de quedar huérfanos, no es necesario desengancharlos.


Si tu puedes. Los editores de eventos tienen referencias a los objetos y evitarían que sean recolectados.

Veamos un ejemplo para ver qué pasa. Tenemos dos clases; uno expone un evento, el otro lo consume:

class ClassA { public event EventHandler Test; ~ClassA() { Console.WriteLine("A being collected"); } } class ClassB { public ClassB(ClassA instance) { instance.Test += new EventHandler(instance_Test); } ~ClassB() { Console.WriteLine("B being collected"); } void instance_Test(object sender, EventArgs e) { // this space is intentionally left blank } }

Observe cómo ClassB no almacena una referencia a la instancia de ClassA; simplemente conecta un controlador de eventos.

Ahora, veamos cómo se recolectan los objetos. Escenario 1:

ClassB temp = new ClassB(new ClassA()); Console.WriteLine("Collect 1"); GC.Collect(); Console.ReadKey(); temp = null; Console.WriteLine("Collect 2"); GC.Collect(); Console.ReadKey();

Creamos una instancia ClassB y mantenemos una referencia a ella a través de la variable temp. Se pasa una nueva instancia de ClassA, donde no almacenamos ninguna referencia en ninguna parte, por lo que queda fuera del alcance inmediatamente después de que el constructor de ClassB finaliza. Hacemos que el recolector de basura se ejecute una vez cuando ClassA ha salido del alcance, y una vez cuando ClassB está fuera de alcance. La salida:

Collect 1 A being collected Collect 2 B being collected

Escenario 2:

ClassA temp = new ClassA(); ClassB temp2 = new ClassB(temp); temp2 = null; Console.WriteLine("Collect 1"); GC.Collect(); Console.ReadKey(); temp = null; Console.WriteLine("Collect 2"); GC.Collect(); Console.ReadKey();

Se crea una nueva instancia de ClassA y se almacena una referencia a ella en la variable de temperatura. Luego se crea una nueva instancia de ClassB, obteniendo la instancia de ClassA en la temperatura que se le pasa, y almacenamos una referencia en temp2. Luego configuramos temp2 para que anule, haciendo que la instancia de ClassB salga del alcance. Como antes, tenemos el recolector de basura ejecutado después de que cada instancia haya salido del alcance. La salida:

Collect 1 Collect 2 B being collected A being collected

Entonces, para concluir; si la instancia que expone un evento queda fuera del alcance, queda disponible para la recolección de elementos no utilizados, independientemente de si hay controladores de eventos conectados o no. Si una instancia que tiene un controlador de eventos conectado a un evento en otra instancia, no estará disponible para la recolección de elementos no utilizados hasta que el controlador de eventos se separe o la instancia a la que está conectado el controlador de eventos esté disponible para la recolección de elementos no utilizados.