2010-04-13 17 views
5

Digamos que tengo dos clases, y ninguno de ellos son componentes de la GUI. Una clase es un objeto de corta duración que se registra para un evento declarado por un objeto B. larga vida Por ejemplo¿Debo deshacerme de los eventos?

public A(B b) 
{ 
    b.ChangeEvent += OnChangeEvent; 
} 

Si A no anula el registro del evento de B, A nunca va a ser el recolector de basura? ¿Necesita A un método de eliminación solo para anular el registro del evento de B?

También hay una segunda pregunta relacionada. Si A y B deberían vivir durante todo el tiempo de ejecución de la aplicación, ¿es necesario cancelar el registro?

Respuesta

3

A su primera pregunta: Sí. B tiene una referencia a A. De esa manera, A vivirá tanto como B. Esta es una buena forma de perder memoria en una aplicación de interfaz de usuario si, por ejemplo, registrarse en un evento como App.OnIdle.

Al segundo: Al final todo será eliminado.

0

Si B contiene una referencia a A, A no obtendrá la basura recopilada a menos que B también sea elegible para la recolección de basura.

No debe necesitar un método de eliminación para esto. Una vez que B tampoco tenga referencias que lo señalen, el recolector de basura será lo suficientemente inteligente como para deshacerse de B y A.

Si ambos están activos durante la vida de la aplicación, no es necesario que elimine el registro del evento.

+0

... a menos que A también sea elegible para recolección de basura. –

+0

Como dijo Jon, ¿qué hay de A? – Sean

+0

@Sean, he invertido B y A. Una vez que las referencias externas se eliminan de B, A también se eliminará. – kemiller2002

1

El lugar adecuado para desconectar el evento sería, como sospecha, estar en el método IDisposable.Dispose de A. Realmente no hay una buena alternativa. Sería inútil intentar desconectar el evento dentro del finalizador/destructor de A, ya que la única forma en que A podría ser elegible para la recolección de basura antes de su desconexión de B sería para B para ser elegible para la recolección de basura; una vez que eso sucedió, la suscripción se convertiría en un punto discutible, por lo que no importaría si se limpiaba o no.

Si es necesario limpiar los eventos de suscriptores abandonados efímeros durante la vida útil de un editor de larga duración, existen formas de hacerlo si las clases de publicación y suscripción cooperan. Por ejemplo, la cara pública del suscriptor del evento puede ser un objeto contenedor que contiene una referencia al suscriptor del evento real, sin que el suscriptor tenga una referencia fuerte a ese objeto público. En ese escenario, la suscripción al evento no evitaría que el objeto público caiga fuera del alcance y sea elegible para la finalización. Un finalizador en el objeto público podría notificar al objeto suscriptor que la suscripción ya no sería necesaria y debería darse de baja. Dado que dicha notificación llegaría de forma asíncrona, el objeto que publica la suscripción debería ofrecer un medio por el cual los suscriptores podrían anularse la suscripción de forma asincrónica. Esto podría hacerse mediante una solicitud normal de "cancelación de suscripción", siempre que el evento de publicación garantice que no sea bloqueante ni esté protegida contra subprocesos; desafortunadamente, la mayoría de los eventos no ofrecen tal garantía.

Cuestiones relacionadas