Puede utilizar expresiones lambda como controladores de eventos provocar una pérdida de memoria?

StackOverflow https://stackoverflow.com/questions/16473

Pregunta

Dicen que tenemos el siguiente método:

private MyObject foo = new MyObject();

// and later in the class

public void PotentialMemoryLeaker(){
  int firedCount = 0;
  foo.AnEvent += (o,e) => { firedCount++;Console.Write(firedCount);};
  foo.MethodThatFiresAnEvent();
}

Si la clase con este método se crea una instancia y el PotentialMemoryLeaker el método se llama varias veces, hacemos memoria de la fuga?

Hay alguna forma de desenganche que lambda controlador de eventos después de que hemos terminado de llamar MethodThatFiresAnEvent?

¿Fue útil?

Solución

Sí, guardarlo en una variable y desengancharlo.

DelegateType evt = (o, e) => { firedCount++; Console.Write(firedCount); };
foo.AnEvent += evt;
foo.MethodThatFiresAnEvent();
foo.AnEvent -= evt;

Y sí, si no, vas a fuga la memoria, como vas a conectar a un nuevo delegado objeto cada vez.También te darás cuenta de esto porque cada vez que se llama a este método, se tirarán a la consola de un número creciente de líneas (no sólo un número creciente, sino por una llamada a MethodThatFiresAnEvent se tirarán a cualquier número de elementos, una vez para cada conectado método anónimo).

Otros consejos

Usted no sólo pérdida de la memoria, que también tendrá su lambda llamado varias veces.Cada llamada de 'PotentialMemoryLeaker' le agregue otra copia de la lambda a la lista de eventos, y de cada copia será llamado al 'AnEvent' es despedido.

También puede ampliar lo que se ha hecho aquí para hacer que los delegados más seguro de usar (no hay pérdidas de memoria)

Su ejemplo sólo se compila a un compilador llamado privada interior de la clase (con campo firedCount y un compilador nombre de método).Cada llamada a PotentialMemoryLeaker crea una nueva instancia de la cierre de la clase a la que donde foo mantiene una referencia por medio de un delegado para que el único método.

Si no referencia el conjunto de objetos que posee PotentialMemoryLeaker, entonces todo eso va a ser el recolector de basura.De lo contrario, puede establecer foo a nulo o vacío foo controlador de eventos de la lista escribiendo esto:

foreach (var handler in AnEvent.GetInvocationList()) AnEvent -= handler;

Por supuesto, usted tendría acceso a la Miobjeto clase privada de miembros.

Sí, de la misma manera que los normales de los controladores de eventos pueden causar fugas.Debido a que el lambda es en realidad cambiado a:

someobject.SomeEvent += () => ...;
someobject.SomeEvent += delegate () {
    ...
};

// unhook
Action del = () => ...;
someobject.SomeEvent += del;
someobject.SomeEvent -= del;

Así que, básicamente, es sólo de la mano de lo que hemos estado utilizando en 2.0 todos estos años.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top