Pregunta

Estoy utilizando varios comportamientos Blend y disparadores en un control de Silverlight. Me pregunto si existe algún mecanismo para separar automáticamente o asegurar que OnDetaching () se llama para un comportamiento o gatillo cuando ya no se utiliza el control (es decir eliminado del árbol visual).

Mi problema es que hay una pérdida de memoria logrado con el control debido a una de las conductas. Se suscribe el comportamiento a un evento en un objeto de larga vida en la anulación OnAttached () y deben darse de baja de ese evento en el OnDetaching () anulan para que pueda convertirse en un candidato para la recolección de basura. Sin embargo, OnDetaching () no parece estar llamada cuando quito el control del árbol visual ... la única manera que puedo conseguir que esto suceda es separando explícitamente los comportamientos problemáticos ANTES de quitar el control y entonces es adecuadamente el recolector de basura .

En este momento mi única solución era crear un método público en el código subyacente para el control que puede atravesar y separar cualquier comportamiento que podrían causar problemas de recolección de basura. Sería hasta el código de cliente saber para llamar a este antes de quitar el control del panel. En realidad no me gusta este enfoque, por lo que estoy buscando algo de forma automática de hacer esto que estoy pasando por alto o una idea mejor.

public void DetachBehaviors()
{
     foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
     {
          behavior.Detach();
     }

     //continue detaching all known problematic behaviors on the control....
}
¿Fue útil?

Solución

Lo que realmente necesita en este caso no es una manera de separar de forma automática, sino garantizar que la referencia contenida en el objeto de larga vida no mantiene el comportamiento (y por lo tanto todo lo demás que tiene una referencia a) de ser recogido de basura.

Esto se acheived mediante la implementación de un patrón de mediador. El concepto es que usted no da el objeto de larga duración a un delegado con una referencia a su Behaviour, en lugar de crear una clase de mediador como un intermediario. Los agregados mediador para el caso de objetos vivido largo y tiene un WeakReference al comportamiento. Cuando el objeto vivido largo desencadena el evento los cheques que el mediador WeakReference sigue vivo, si así se llama a un método en él para transmitir el evento. Si cuando el evento ocurre, los hallazgos que el mediador WeakReference ya no está vivo que se separe de su controlador de eventos del objeto de larga vida.

Por lo tanto no hay nada que impida el comportamiento y todo lo demás que participan de ser basura recogida toda la que es izquierda es un pequeño ejemplo de mediador con una referencia muerto todavía unido al objeto de larga vida. Dado que estos mediadores son muy pequeñas que no representan un problema real e incluso los que desaparecerán la próxima vez que se activa el evento.

Afortunadamente, usted no tiene que construir estas cosas por sí mismo que otros ya lo han hecho. Se llama la WeakEventListener. Este blog: Destacando una "contribución débil"; Mejoras hacen que la prevención de pérdidas de memoria con WeakEventListener aún más fácil! tiene un excelente conjunto de enlaces sobre el tema.

Otros consejos

Joost van Schaik ofrece una alternativa manera de limpiar las referencias de sus comportamientos asociados, evitando al mismo tiempo el problema con la pérdida de memoria. Depende de hacer el trabajo de limpieza utilizando los delegados de los eventos con y sin carga de la AssociatedObject.

También ofrece un código de fragmento para generar recibos de sus comportamientos asociados.

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