silverlight memory-leaks garbage-collection expression-blend attachedbehaviors

Llamada automática a OnDetaching() para comportamientos de Silverlight



memory-leaks garbage-collection (2)

Lo que realmente necesita en este caso no es una manera de desconectarse automáticamente, sino asegurarse de que la referencia mantenida por el objeto de larga duración no conserve el comportamiento (y, por lo tanto, todo lo demás a que hace referencia) de ser basura recolectada.

Esto se logra implementando un patrón de Mediator. El concepto es que no le das un delegado a un objeto de larga vida con una referencia a tu Behaviour , sino que creas una clase Mediator como intermediario. El mediador se une al evento de objetos de larga vida y tiene una WeakReference para el comportamiento. Cuando el objeto de larga duración WeakReference el evento, el mediador comprueba que la WeakReference todavía está activa, en caso afirmativo, llama a un método para transmitir el evento. Si cuando ocurre el evento, el mediador encuentra que la WeakReference ya no está viva, separa su manejador de eventos del objeto de larga duración.

Por lo tanto, no hay nada que detenga el comportamiento y todo lo demás involucrado en la recolección de basura, todo lo que queda es una pequeña instancia de mediación con una referencia muerta todavía asociada al objeto de larga vida. Dado que estos mediadores son pequeños, no representan un problema real e incluso esos desaparecerán la próxima vez que se desate el evento.

Afortunadamente no tienes que construir esto tú mismo, otros ya lo han hecho. Se llama WeakEventListener . Este blog: resaltando una contribución "débil"; ¡Las mejoras hacen que prevenir fugas de memoria con WeakEventListener sea aún más fácil! tiene un excelente conjunto de enlaces sobre el tema.

Estoy usando varios comportamientos y disparadores de mezcla en un control Silverlight. Me pregunto si hay algún mecanismo para separar automáticamente o asegurar que OnDetaching () se llame para un comportamiento o desencadenar cuando el control ya no se usa (es decir, eliminado del árbol visual).

Mi problema es que hay una pérdida de memoria administrada con el control debido a uno de los comportamientos. El comportamiento se suscribe a un evento en algún objeto de larga duración en la anulación OnAttached () y debe anular su suscripción de ese evento en la anulación OnDetaching () para que pueda convertirse en un candidato para la recolección de elementos no utilizados. Sin embargo, nunca parece que se llame a OnDetaching () cuando elimino el control del árbol visual ... la única manera en que puedo lograr que ocurra es separando explícitamente los comportamientos problemáticos ANTES de quitar el control y luego es correctamente recolectada. .

En este momento, mi única solución era crear un método público en el código subyacente para el control que puede pasar y separar cualquier comportamiento conocido que pueda causar problemas de recolección de basura. Depende del código del cliente saber llamar esto antes de quitar el control del panel. Realmente no me gusta este enfoque, por lo que estoy buscando una manera automática de hacer esto que estoy pasando por alto o una mejor sugerencia.

public void DetachBehaviors() { foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot)) { behavior.Detach(); } //continue detaching all known problematic behaviors on the control.... }


Joost van Schaik ofrece una forma alternativa de limpiar referencias de comportamientos adjuntos, al tiempo que evita el problema con la pérdida de memoria. Depende de realizar el trabajo de limpieza utilizando delegados de los eventos Cargados y Descargados del AssociatedObject.

También ofrece un fragmento de código para generar stubs para comportamientos adjuntos.