2009-11-27 10 views
12

Sto lavorando per implementare un'aggregazione di eventi con Prism. Ho alcuni moduli e voglio che ognuno di loro si abboni agli eventi che dicono loro quando vengono richiesti. Ho iniziato a fare un semplice esempio con sia sottoscritto che editore nella shell. Nessun problema lì. Adesso; quando sposto gli abbonati verso i miei moduli non vengono attivati. Ciò che è ancora più strano è che in realtà ha funzionato un paio di volte, tutte cose che sono stato sospeso in una pausa. Quindi mi sembra di essere in condizioni di gara, ma non capisco perché.Aggregazione evento Prism - sottoscrittore non attivato

Presupposto fatto: Non ho bisogno di configurare IEventAggregator ovunque - ad es. registrarsi nel contenitore IoC? Questo è incorporato in Prism tale che ho solo un'istanza dell'aggregatore di eventi, giusto?

Quindi, la domanda è fondamentalmente come/dove/quando dovrei impostare i miei abbonati. C'è un ordine specifico su cose ecc? Nel mio esempio semplificato ho un modulo MyModule. Il programma di avvio automatico aggiungerà MyModule al catalogo - che lo rende inizializzato:

catalog.AddModule(typeof(MyModule)); 

MyModule memorizzerà l'aggregatore e di utilizzare per la sottoscrizione al MyModuleRequestedEvent. Utilizza anche un registro di menu per registrarsi nel menu dell'applicazione. L'idea è che alla fine, facendo clic sul menu, l'evento venga attivato, notificando a MyModule che è stato richiesto. Quindi voglio che sia la responsabilità di MyModule per capire cosa fare ulteriormente.

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"); 
} 

Ora ho un pulsante nella shell che pubblicherà questo evento. La shell ottiene lo stesso aggregatore di eventi (?) Quando viene risolto.

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

Note:

  • hanno verificato che l'evento viene pubblicato. Anche l'aggiunta di un sottoscrittore nella shell renderà questo sottoscrittore ricevere l'evento.
  • Ancora; l'utente di MyModule non viene attivato. Tuttavia, è - stranamente - stato in alcune occasioni.
  • Non uso l'input per l'evento. Sembrava che avessi bisogno di un po 'di input, quindi sono andato con un bool fittizio. Posso liberarmi di questo ..?
+1

Sembra che tu stia ricevendo due EventAggregator; usa il debugger per creare un ID oggetto per entrambi, così puoi controllarlo e farcelo sapere. – GraemeF

+0

Grazie per il suggerimento! Lo ha fatto, ed è in effetti lo stesso EventAggregator che viene utilizzato per iscriversi nel modulo e per la pubblicazione. Entra prima nel costruttore di Shell. Ha fatto il "Crea ID oggetto". Ho ottenuto 1 #. Quindi premi il punto di interruzione in MyModule.Initialize e verifica che l'aggregatore abbia ID 1 #. Inoltre, quando si preme il pulsante per attivare la pubblicazione, vedo che l'aggregatore utilizzato è 1 #. – stiank81

risposta

25

L'aggregatore di eventi Prism utilizza riferimenti deboli per il collegamento agli eventi. Questo serve a prevenire perdite di memoria dai gestori di eventi.

Una volta eseguito l'inizializzatore del modulo, viene eliminato, quindi il gestore eventi viene distrutto prima che l'evento venga attivato. Puoi dire a Prisma di mantenere il gestore di eventi usando un sovraccarico di Abbonati.

evnt.Subscribe(MyModuleRequested, true); 

Come modello, tendo mettere tutti gli abbonati di eventi in una classe separata, e chiamare quella classe dai moduli metodo Inizializza. In questo modo gli eventi rimangono vivi ma separati mentre il modulo è ancora distrutto.

+0

Perfetto! E il tuo schema ha senso - quindi metto un gestore di eventi minimo in una classe separata. Grazie..! – stiank81

+0

Ho anche riscontrato questo problema, l'aggiunta di una vista a una regione di Prism impedisce l'eliminazione del mio modulo, sto facendo qualcosa di sbagliato con la registrazione della mia regione? Conoscete la documentazione relativa alla durata del modulo e alle viste di registrazione consigliate? – BenCr

2

Quindi, ho appena ottenuto una teoria, ma non ho tempo per testarlo in questo momento .. Lo farò domani.

Domanda: Aggiungerà moduli al ModuleCatalogue per mantenerli in vita? Ho pensato che sarebbe. Quindi, il MyModule dovrebbe rimanere attivo e quindi verrà attivato quando l'evento verrà pubblicato.

Tuttavia, se questo non mantiene attivo il modulo, è ovvio che sarà difficile rispondere all'evento. L'oggetto modulo muore, ma non annulla la sottoscrizione - quindi vedrò il sottoscrittore nell'elenco EventAggregator, ma l'utente non è più in giro. Anche; Ho accennato al fatto che in effetti funziona occasionalmente - il che sarebbe il caso se il garbage collector non avesse il tempo di estrarre la spazzatura prima che l'evento venisse attivato.

Questo suona come il caso? Se è così, non ho ancora pensato a una soluzione, quindi puoi suggerirne una in un thread di risposta diverso.

Quindi; qual è il ModuleCataloge comunque?Solo una lista mantenuta per l'inizializzazione e poi gettata via?

Problemi correlati