2010-03-28 15 views
12

¿Hay una forma simple de iterar en todos los manipuladores suscritos a un evento determinado? Mi problema es que los clientes se suscriben, pero olvidan cancelar la suscripción, por lo que se produce una pérdida de memoria. Necesito una forma para que un objeto desconecte todos los manejadores de sus eventos en el método Dispose para que no ocurra una fuga, al menos no por los eventos.C# Cómo cancelar la suscripción a todos los controladores de eventos de un evento determinado?

Respuesta

11

conjunto nulo a su evento: MyEvent = null;

Pero es realmente mejor para hacer que los clientes darse de baja de su evento.

+1

No es posible configurar un evento en nulo, en C#. –

+8

En realidad es posible, si estás dentro de la clase donde se declaró el evento. –

+1

Tiene razón. –

9

Un enfoque alternativo es utilizar el llamado patrón de "delegado débil". Cuando utiliza esta técnica, el evento hace referencia a los clientes solo usando WeakReference que no los mantiene en la memoria. Los clientes serán recogidos basura cuando ya no se los referencia desde otra parte de la aplicación (y el controlador también puede ser no registrado automáticamente cuando se recopila el cliente).

Esto se usa generalmente para resolver el problema con el "olvido" de los clientes para darse de baja de un evento .NET, por lo que parece que esto podría ser adecuado para su problema.

7

La pérdida de memoria ocurre solo si otro objeto (oyente) muere antes que su objeto (origen del evento). En este caso, el origen del evento aún conserva la referencia al oyente, lo que impide que se recopile el oyente. Cuando el origen del evento muere, el oyente no suscrito también puede ser recogido.

Si el origen del evento muere antes del oyente, esto no impide que el oyente se recopile más tarde, cuando todas las demás referencias al mismo se establecen en nulo.

Esto significa que el origen del evento El método de eliminación no es el lugar correcto para resolver este problema. Puede resolverse solo en un código de escucha. Simplemente hablando, no puede hacer nada, excepto pedirle a sus clientes que escriban un código limpio.

1

En el momento de escribir, la respuesta más precisa es la menos popular.

Puede anular el controlador de eventos, pero esto se eliminará de todos modos después de que su propietario sea desactivado; no está mal que sea súper ordenado, pero como Alex dice, no es donde está el problema.

La clase de origen de Adi permitirá que los objetos de escucha se recopilen cuando se recopila, no hay duda. Entonces, el problema es que el objeto fuente de Adi se mantiene abierto, posiblemente a partir de una larga cadena de referencias en el código de su cliente.

La siguiente publicación de blog también analiza una solución que Adi está describiendo y explica por qué no es necesaria.

http://weblogs.sqlteam.com/mladenp/archive/2007/10/24/C-Care-about-Event-Memory-Leaks-with-Delegate.GetInvocationList.aspx

Cuestiones relacionadas