Pregunta

Estoy trabajando en la implementación de una agregación de eventos con Prism. Tengo algunos módulos y quiero que cada uno de ellos se suscriba a eventos que les indiquen cuándo se solicitan. Comencé haciendo un ejemplo simple con suscriptor y publicador en el shell. No hay problemas allí. Ahora; cuando muevo los suscriptores a mis módulos, no se activan. Lo que es aún más extraño es que en realidad ha funcionado varias veces, todas las cuales he estado pendiente en un punto de interrupción. Entonces me parece que es una condición de raza, pero no entiendo por qué.

Supuesto realizado: No necesito configurar el IEventAggregator en ningún lugar, por ejemplo. Registrarse en el contenedor IoC? Esto está integrado en Prism, de modo que solo tengo una instancia del agregador de eventos, ¿verdad?

Entonces, la pregunta es básicamente cómo / dónde / cuándo debo configurar mis suscriptores. ¿Hay un orden específico en cosas, etc.? En mi ejemplo simplificado tengo un módulo MyModule. Bootstrapper agregará MyModule al catálogo, lo que lo inicializará:

catalog.AddModule(typeof(MyModule));

MyModule almacenará el agregador y lo usará para suscribirse a MyModuleRequestedEvent. También utiliza un registro de menú para registrarse en el menú de la aplicación. La idea es que al hacer clic en el menú se active el evento, notificando a MyModule que se ha solicitado. Entonces quiero que MyModule sea responsable de averiguar qué hacer más.

public MyModule(IEventAggregator aggregator, IApplicationMenuRegistry menu)
{
    _applicationMenu = menu;
    _aggregator = aggregator;
}

public void Initialize()
{
    var evnt = _aggregator.GetEvent<MyModuleRequestedEvent>();
    evnt.Subscribe(MyModuleRequested);
    _applicationMenu.RegisterMenuItem("MyModule", evnt);
}

public void MyModuleRequested(bool b)
{
    MessageBox.Show("MyModule requested");
}

Ahora, tengo un botón en mi shell que publicará este evento. El shell obtiene el mismo agregador de eventos (?) Cuando se resuelve.

public Shell(IEventAggregator aggregator)
{
    InitializeComponent();
    var evnt = aggregator.GetEvent<MyModuleRequestedEvent>();
    EventTriggerButton.Click += (s, e) => evnt.Publish(true);
}

Notas:

  • Han verificado que el evento está publicado. Agregar un suscriptor en el shell también hará que este suscriptor reciba el evento.
  • de nuevo; el suscriptor en MyModule no se activa. Sin embargo, ha sido, extrañamente, en algunas ocasiones.
  • No uso la entrada para el evento. Parecía que necesitabas tener algún tipo de entrada, así que solo fui con un tonto bool. ¿Puedo deshacerme de esto ..?
¿Fue útil?

Solución

El agregador de eventos Prism utiliza referencias débiles para enlazar a los eventos. Esto es para evitar pérdidas de memoria de los controladores de eventos.

Una vez que se haya ejecutado un inicializador de módulo, se eliminará, por lo que su controlador de eventos se destruirá antes de que se desencadene el evento. Puede decirle a Prism que mantenga el controlador de eventos utilizando una sobrecarga de Suscribirse.

evnt.Subscribe(MyModuleRequested, true);

Como patrón, tiendo a colocar a los suscriptores de eventos en una clase separada y llamar a esa clase desde el método de inicialización de los módulos. De esa manera, los eventos se mantienen vivos pero separados mientras el módulo aún se destruye.

Otros consejos

Entonces, acabo de recibir una teoría, pero no hay tiempo para probarlo ahora mismo. Lo haré mañana.

Pregunta: ¿Agregar módulos al Catálogo de Módulos los mantendrá vivos? Supuse que lo haría. Por lo tanto, MyModule debe permanecer vivo y luego se activará cuando se publique el evento.

protected override IModuleCatalog GetModuleCatalog()
{
    var catalog = new ModuleCatalog();
    catalog.AddModule(typeof(MyModule));
    return catalog;
}

Sin embargo, si esto no mantiene el módulo activo, es obvio que le será difícil responder al evento. El módulo-objeto muere, pero no cancela la suscripción; por lo tanto, veré al suscriptor en la lista de agregadores de eventos, pero el suscriptor ya no estará. También; Mencioné que, de hecho, sí funciona ocasionalmente, lo que sería el caso si el recolector de basura no tuviera tiempo para sacar la basura antes de que se desencadene el evento.

¿Esto suena como el caso? Si es así, aún no he pensado en una solución, así que puedes sugerir una en un hilo de respuesta diferente.

Entonces; ¿Qué es el ModuleCataloge de todos modos? ¿Solo una lista guardada para la inicialización y luego desechada?

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