Si mi software tiene dos instancias de objeto, una de las cuales 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?¿Debo eliminar las suscripciones a eventos de los objetos antes de que queden huérfanos?
Respuesta
Sí, lo haces. Los editores de eventos tienen referencias a los objetos y evitarían que sean recolectados.
Veamos un ejemplo para ver qué sucede. 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
}
}
Nota cómo ClassB no almacena una referencia a la instancia claseA; simplemente conecta un controlador de eventos.
Ahora, veamos cómo se recogen 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 de ClassB y la mantenemos como referencia 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 una referencia a ella se almacena en la variable TEMP. 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.
Sólo es necesario desenganchar eventos si el objeto exponer los eventos es de larga duración, pero el objeto de enganche el caso de otro modo sería de corta duración (y obtener el recolector de basura con bastante rapidez).
En este caso, el hecho de que no se desenganche causará lo que equivale a una pérdida de memoria, porque 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 al objeto efímero. Como ese delegado aún hace referencia al objeto efímero, no se puede recolectar basura.
Los eventos estáticos duran por definición, viven hasta que finaliza el programa. 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.
La suscripción a un evento da como resultado una fuerte referencia al suscriptor. Esto se debe a que, bajo las coberturas, 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 cierto, es decir, el objeto suscrito no tiene ninguna referencia al editor.
- 1. ¿Debo eliminar los detectores de eventos antes de eliminar los elementos?
- 2. Borrar todas las suscripciones a eventos (clonadas)
- 3. ¿Qué debo hacer antes de eliminar elementos en un vector de punteros a objetos asignados dinámicamente?
- 4. eliminar automáticamente referencia a los objetos de supresión en MongoDB
- 5. ¿Cómo puedo borrar las suscripciones de eventos en C#?
- 6. ¿Debo deshacerme de los eventos?
- 7. ¿Debo eliminar un controlador de eventos?
- 8. ¿Debo eliminar TestFlight antes de enviarme a la App Store?
- 9. ¿Debo desvincular el evento jquery antes de eliminar el elemento?
- 10. Evite suscripciones de eventos duplicados en C#
- 11. ¿Es necesario eliminar los detectores de eventos de JavaScript antes de eliminar el elemento al que están conectados?
- 12. ¿Cómo debo pasar objetos a las subrutinas?
- 13. plantillas de prueba RSpec que se queden
- 14. ¿Puede EF eliminar automáticamente los datos que quedan huérfanos, donde no se elimina el padre?
- 15. ¿Debo darme de baja de los eventos?
- 16. ¿Debo eliminar este tipo de controlador de eventos?
- 17. ¿Debo anular la suscripción a todos los controladores de eventos?
- 18. ¿Hay alguna manera de eliminar los detectores de eventos desconocidos de los objetos?
- 19. JQuery: Eliminar eventos "OnClick" de las etiquetas 'a'
- 20. ¿Debo llamar a MessageDigest.reset() antes de usarlo?
- 21. ¿Debo removeTarget antes addTarget
- 22. ASP.net MVC ValidationSummary siempre que se queden
- 23. Cómo eliminar todos los punteros a objetos en java
- 24. ¿Debo eliminar explícitamente los depósitos SWT?
- 25. Eventos antes de $ (documento) .ready
- 26. jQuery vincular el detector de eventos antes que otro
- 27. ¿Cuáles son los beneficios de tener eventos que se ajusten a las pautas de la red?
- 28. Parece que Delphi está destruyendo objetos antes de que sea
- 29. ¿Cuándo debería eliminar observadores? Error al desasignar objetos antes de eliminar observadores
- 30. eliminar todos los objetos de una uiview?