Modelos de evento débil

En las aplicaciones típicas, es posible que los controladores asociados a los orígenes de eventos no se destruyan en coordinación con el objeto de agente de escucha que adjuntó el controlador al origen. Esta situación puede provocar pérdidas de memoria. Windows Presentation Foundation (WPF) introduce un modelo de diseño concreto que se puede usar para resolver este problema; para ello, proporciona una clase de administrador dedicada para eventos concretos e implementa una interfaz para los agentes de escucha de ese evento. Este modelo de diseño se denomina modelo de evento débil.

¿Por qué implementar el modelo de evento débil?

Realizar escuchas de eventos puede provocar pérdidas de memoria. La técnica típica para realizar escuchas de eventos consiste en utilizar la sintaxis específica del lenguaje que asocia un controlador a un evento en un origen. Por ejemplo, en C#, esa sintaxis es: source.SomeEvent += new SomeEventHandler(MyEventHandler).

Esta técnica crea una referencia segura desde el origen de evento al agente de escucha de evento. En general, al adjuntar un controlador de eventos para un agente de escucha, la duración de objeto del origen influye en la duración de objeto del agente (a menos que el controlador de eventos se quite explícitamente). Sin embargo, en determinadas circunstancias puede ser conveniente controlar la duración de objeto del agente de escucha mediante otros factores, tales como si pertenece actualmente al árbol visual de la aplicación, no mediante la duración del origen. Cada vez que la duración de objeto del origen es superior a la del agente de escucha, el modelo de eventos normal provoca una pérdida de memoria: el agente de escucha se mantiene activo más tiempo del previsto.

El modelo de evento débil está diseñado para resolver este problema de pérdida de memoria. Se puede utilizar el modelo de evento débil cada vez que un agente de escucha necesita registrarse para un evento, pero el agente de escucha no sabe explícitamente cuándo cancelar el registro. También se puede usar el modelo de evento débil cuando la duración de los objetos del origen supera la duración útil de los objetos del agente de escucha. (En este caso, útil es determinado por el desarrollador). El modelo de evento débil permite al agente de escucha registrarse para el evento y recibirlo sin que ello afecte en modo alguno a sus características de duración de objeto. En efecto, la referencia implícita del origen no determina si el agente de escucha es apto para la recolección de elementos no utilizados. Se trata de una referencia débil, concepto del que toman su nombre el modelo de evento débil y las APIs relacionadas. El agente de escucha puede someterse a la recopilación de elementos no utilizados o destruirse de alguna otra forma, y el origen puede continuar sin conservar las referencias al objeto que se ha destruido no recopilables en el controlador.

¿Quién debe implementar el modelo de evento débil?

Implementar el modelo de evento débil resulta interesante principalmente para los autores de controles. El autor de un control es responsable en gran medida del comportamiento y la contención del control y del efecto que ejerce en las aplicaciones en las que se inserta. Esto incluye el comportamiento de la duración de objeto del control, y en particular de la administración del problema de pérdida de memoria descrito.

Algunos escenarios se prestan de forma inherente a la aplicación del modelo de evento débil. Un escenario de este tipo es el enlace de datos. En el enlace de datos, es común que el objeto de origen sea completamente independiente del objeto de agente de escucha, que es un destino de un enlace. El modelo de evento débil ya se aplica a muchos aspectos del enlace de datos de WPF en lo relativo a cómo se implementan los eventos.

Cómo implementar el modelo de evento débil

La implementación del modelo de evento débil se divide en los tres aspectos siguientes:

  • Derivar un administrador de la clase WeakEventManager.

  • Implementar la interfaz IWeakEventListener en cualquier clase que desee registrar agentes de escucha para el evento débil sin generar una referencia segura al origen.

  • Al registrar los agentes de escucha, no utilice los descriptores de acceso convencionales de agregar y quitar del evento donde desea que el agente de escucha utilice el modelo. En su lugar, utilice las implementaciones RemoveListener y AddListener en el objeto WeakEventManager dedicado para ese evento.

WeakEventManager

Para implementar el modelo de evento débil, normalmente se crea una clase de administrador con una relación 1:1 al evento. Por ejemplo, si tiene un evento denominado Spin, crearía una clase SpinEventManager que es el administrador del evento débil dedicado para el evento. Si el evento existe en más de una clase de origen y, en general, se comporta igual en todas las clases y comparte el mismo tipo de datos de evento, puede utilizarse el mismo administrador para cada evento.

Cuando se deriva de la clase WeakEventManager, se reemplazan dos métodos virtuales y se exponen diversos miembros más cuyos nombres no se rigen específicamente por una plantilla virtual, pero deben existir de todos modos. Las invalidaciones se utilizan para iniciar o finalizar el modo de entrega de eventos por la infraestructura de WPF. Los demás miembros proporcionan la funcionalidad para que sus propias implementaciones de IWeakEventListener puedan usar WeakEventManager para adjuntar agentes de escucha al evento.

Para obtener más información sobre cómo derivar de WeakEventManager, vea la sección "Notas a herederos" en el tema de referencia WeakEventManager.

IWeakEventListener

La interfaz IWeakEventListener tiene un solo método denominado ReceiveWeakEvent. La implementación de ReceiveWeakEvent debe ser centralizada y dirigir cualquier referencia de evento que exista en esa clase al objeto WeakEventManager adecuado.

Para obtener más información acerca de la implementación de la interfaz IWeakEventListener, vea la sección "Notas para los implementadores" en el tema de referencia del método ReceiveWeakEvent.

Asociar agentes de escucha

Supongamos que tiene un evento ClockwiseSpin (definido por un tipo Spinner) que es un evento convencional. Si tiene una clase de agente de escucha SpinListener que desea usar como agente de escucha, la técnica convencional (sin utilizar el modelo de evento débil) para adjuntar el controlador sería emplear el operador += como sigue:

spinnerInstance.ClockwiseSpin += new EventHandler(MyOnCWSpinHandler);

Si tiene una clase que implementa IWeakEventListener y que tiene en cuenta el evento ClockwiseSpin y su administrador en la implementación, la sintaxis que debe usar para el modelo de evento débil es:

ClockwiseSpinEventManager.AddListener(spinnerInstance, this);

La lógica de control del evento se especifica dentro de uno de los casos de la implementación de ReceiveWeakEvent en la clase, no como un controlador basado en delegado convencional.

Implementar el modelo para eventos externos

Un aspecto interesante del modelo de evento débil es que le permite implementar el modelo con un evento que no forme parte de la base de código. Desde la perspectiva del origen, la manera de asociar los controladores a su evento no varía, y se controla por WeakEventManager. Solo es necesario definir WeakEventManager para ese evento y, a continuación, tener en cuenta ese evento como parte de la lógica de ReceiveWeakEvent en cualquier agente de escucha probable que desee usar el modelo de evento débil para escuchar ese evento.

Vea también

Referencia

WeakEventManager

IWeakEventListener

Conceptos

Información general sobre eventos enrutados

Información general sobre el enlace de datos