2010-09-07 12 views
6

Si es así, ¿hay una manera de unwire de forma global para todos los eventos cableadas¿El evento no conectado es una pérdida de memoria?

Editar: decir, por ejemplo. Tengo objetos, cada uno etiquetado con un evento como orm.NatureChanged += Nature_Changed; Etiqueto estos eventos cuando creo cada instancia de orm. Si no me hubiera desconectado por medios como orm.NatureChanged -= Nature_Changed;, ¿provocaría una pérdida de memoria?

+0

¿Qué estás preguntando? – SLaks

+2

¿Te refieres a un evento que no se quita? – Bobby

+0

¿Está preguntando sobre eventos/delegados que tienen una lista de invocación vacía? – Oded

Respuesta

5

No, porque cuando Unwire un evento, el delegado (que es un objeto), que estaba conectado al evento es ya no está enraizado, y se recopilará cuando el GC lo considere oportuno. Esto supone, por supuesto, que el delegado del evento no está conectado a múltiples controladores, en cuyo caso no se recopilará hasta que no esté conectado desde todos los eventos.

+0

¡Genial! Entonces, ¿hay alguna forma de desenrollar globalmente múltiples manipuladores? –

+1

@Avatar: a menos que use el reflejo (y no lo haga), es imposible acceder a la lista de invocación de un evento fuera de la clase declarante. Entonces, no. –

+2

Supongo que podría encontrar alguna forma manual de rastrear el evento que estaba conectado, pero esto será engorroso y no obtendrá mucho de él. Probablemente desperdicie más memoria al rastrear el evento para desenrollarlo que simplemente dejarlo funcionar y dejar que el administrador lo elimine cuando lo necesite. – kemiller2002

2

No se trata de una pérdida de memoria, simplemente no engancha a ningún controlador a ese evento si no están cableados, automáticamente o de lo contrario. Entonces el evento no se dispara a nadie, se limpia y la vida continúa.

Esta conversación habla sobre este tema: How do events cause memory leaks in C# and how do Weak References help mitigate that?

ver algunos antecedentes aquí: What does AutoEventWireUp page property mean?

+0

el enlace 3662842 fue increíble. Realmente genial. Estaba pensando en preguntar sobre el lister = null explicado en la sesión de respuesta. Fue realmente útil. –

6

Independientemente de lo que pregunte, la respuesta técnica a su pregunta es "no". Técnicamente, a menos que descubras un error en el CLR, no hay verdaderas "fugas de memoria" con los objetos administrados (eso es una gran parte de lo que los convierte en una buena cosa). Para responder a lo que creo que en realidad está pidiendo, sin embargo, parece que usted está pidiendo una de dos cosas:

  1. ¿Hay algo que hay que hacer con los eventos que no tienen ningún delegados adscrito a los mismos ?
  2. ¿Puede un evento evitar que el recolector de basura limpie los objetos?

La respuesta a la primera pregunta es simplemente "no". Muévete, nada que ver aquí.

La respuesta a la segunda se ha discutido extensamente aquí en SO y otras áreas de la web. La versión corta es que un controlador de eventos adjunto significa que el GC considerará la instancia de destino como "alcanzable" por la instancia de activación de eventos. Este puede hacer que los objetos permanezcan en la memoria más tiempo de lo esperado, ya que esta accesibilidad es algo transparente para el usuario (desarrollador) debido a la forma en que se construyen los delegados.

En otras palabras, supongamos que tengo dos objetos: Productor y Consumidor. El productor dispara un evento que el Consumidor ... consume.

public class Producer 
{ 
    public event EventHandler OmgIDidSomething; 
} 

public class Consumer 
{ 
    public void AttachTo(Producer producer) 
    { 
     producer.OmgIDidSomething += new EventHandler(producer_OmgIDidSomething); 
    } 

    private void producer_OmgIDidSomething(object sender, EventArgs e) 
    { 
     // ... 
    } 
} 

En este ejemplo, cualquier instancia de Consumer donde AttachTo se llama permanecerá accesible en cuanto a la GC es que se trate hasta la instancia de Producer que concede a es elegible para la recolección, debido a que el delegado detrás de la puesta en práctica de el evento OmgIDidSomething tiene una referencia a la instancia de Consumer a la que corresponde.

+0

Mi pregunta es la segunda que mencionaste anteriormente. –

2

Si quiso decir si los eventos que no obtienen sin conexión pueden provocar una pérdida de memoria, la respuesta es que sí puede si la duración real del objeto que contiene el evento delegado es mucho mayor que la vida útil del objeto a lo que el delegado se refiere.Por ejemplo, si el enumerador de una colección enganchó un evento CollectionChanged, y alguien debía obtener enumeradores sin deshacerse de ellos, cada vez que se enumerara la colección (sin eliminar el enumerador) se crearía un nuevo objeto enumerador que permanecería en la memoria mientras como la colección subyacente.

Cuestiones relacionadas