2008-11-18 14 views
155

Si tengo el siguiente código:¿Los controladores de eventos detienen la recolección de elementos no utilizados?

MyClass pClass = new MyClass(); 
pClass.MyEvent += MyFunction; 
pClass = null; 

Will pClass ser basura recogida? ¿O seguirá dando vueltas disparando sus eventos cada vez que ocurran? ¿Tendré que hacer lo siguiente para permitir la recolección de basura?

MyClass pClass = new MyClass(); 
pClass.MyEvent += MyFunction; 
pClass.MyEvent -= MyFunction; 
pClass = null; 
+9

Voy a sugerir tentativamente a los lectores interesados ​​en esta pregunta que podría valer la pena familiarizarse con los eventos livianos/patrones de eventos débiles, que NO evitan que se produzca la recolección de basura. Un buen SO arranque de este tema es http://stackoverflow.com/questions/185931/weakreference-and-event-handling – fostandy

+13

Nota para la posteridad: establecer la referencia a null simplemente retrasa al recolector de basura extendiendo por una línea el alcance de la referencia. .NET no es VB6. –

Respuesta

172

Para la pregunta específica "Will pClass ser basura recogida": la suscripción de evento no tiene ningún efecto sobre la recaudación de pClass (como el editor).

Para GC en general (en particular, el objetivo): depende de si MyFunction es estático o está basado en instancias.

Un delegado (como una suscripción de evento) a un método de instancia incluye una referencia a la instancia. Entonces, sí, una suscripción a un evento evitará GC. Sin embargo, tan pronto como el objeto que publica el evento (pClass anterior) es elegible para la recopilación, esto deja de ser un problema.

Tenga en cuenta que esto es unidireccional; es decir, si tenemos:

publisher.SomeEvent += target.SomeHandler; 

luego "editor" mantendrá "objetivo" vivo, pero "objetivo" no va a mantener "editor" vivo.

Así que no: si pClass se va a recopilar de todos modos, no es necesario cancelar la suscripción de los oyentes. Sin embargo, si pClass era de larga vida (más larga que la instancia con MyFunction), entonces pClass podría mantener viva esa instancia, por lo que sería necesario para anular su suscripción si desea que se recopile el objetivo.

Los eventos estáticos, sin embargo, por esta razón, son muy peligrosos cuando se usan con manejadores basados ​​en instancias.

+0

Gracias, eso es lo que sospechaba. –

+5

Bueno, si la pregunta es "pClass será basura recolectada", entonces la respuesta "depende si ..." no es realmente correcta. No depende de nada, como el mismo Marc nota más abajo. –

+0

@Tor - lo suficientemente claro: aclararé –

5

Sí, pClass será basura recolectada. La suscripción al evento no implica que exista ninguna referencia a pClass.

Así que no, no tendrá que separar el controlador para que pClass sea basura.

6

En el momento en que una pieza de memoria ya no se referencia, se convierte en un candidato para la recolección de basura. Cuando la instancia de su clase queda fuera del alcance, ya no se hace referencia a su programa. Ya no se usa y, por lo tanto, se puede recolectar de forma segura.

Si no está seguro de que algo se recoja, hágase la siguiente pregunta: ¿todavía existe una referencia al respecto? Los manejadores de eventos son referenciados por la instancia del objeto, y no al revés.

0

pClass se recogerá la basura. Sin embargo, si el fragmento de código anterior está dentro de otra clase, la instancia de esa clase podría no borrarse si no establece pClass en null.

Cuestiones relacionadas