Domanda

In un segnale digitale sistema di acquisizione, spesso dati è spinto in un osservatore nel sistema da un thread.

esempio Wikipedia/Observer_pattern:

foreach (IObserver observer in observers)
    observer.Update(message);

Quando, per esempio,un'azione dell'utente (come ad esempiouna GUI-thread richiede i dati per interrompere il flusso, si vuole rompere il soggetto osservatore connessione, e anche smaltire l'osservatore complessivamente.

Uno potrebbe obiettare:si dovrebbe interrompere l'origine dei dati, e di attendere per un sentinel valore di disporre della connessione.Ma che avrebbe sofferto di più la latenza del sistema.

Naturalmente, se i dati di pompaggio thread ha appena chiesto l'indirizzo dell'osservatore, si potrebbe trovare è l'invio di un messaggio a un distrutto oggetto.

Qualcuno ha creato un 'ufficiale' di un Modello di Progettazione per contrastare questa situazione?Non dovrebbero?

È stato utile?

Soluzione

Se vuoi avere i dati di origine per essere sempre sicuro di concorrenza, si dovrebbe avere almeno un puntatore che è sempre sicuri da usare.Quindi l'Osservatore oggetto deve avere una durata di vita che non è finito prima che i dati di origine.

Questo può essere fatto solo l'aggiunta di Osservatori, ma non rimuoverli.Si potrebbe avere ogni osservatore non fare l'implementazione di base di per sé, ma lo hai delegare questo compito a un ObserverImpl oggetto.È possibile bloccare l'accesso a questo impl oggetto.Questo è un grosso problema, ma solo la GUI unsubscriber sarebbe bloccato per un po ' di tempo nel caso in cui l'osservatore è occupato utilizzando il ObserverImpl oggetto.Se GUI reattività sarebbe un problema, è possibile utilizzare un qualche tipo di concorrenti di lavoro-coda con un meccanismo di cancellazione di lavoro ha spinto su di esso.( come PostMessage in Windows )

Quando la disiscrizione, basta sostituire l'implementazione di base per un manichino di attuazione.Di nuovo questa operazione dovrebbe afferrare il blocco.Questo sarebbe infatti introdurre alcune in attesa per i dati di origine, ma dal momento che è solo un [ lock - puntatore swap - unlock ] si potrebbe dire che questo è abbastanza veloce per le applicazioni in tempo reale.

Se si desidera evitare di accatastare Osservatore oggetti che contengono solo un manichino, è necessario fare un qualche tipo di contabilità, ma questo potrebbe ridursi a qualcosa di banale come un oggetto contiene un puntatore all'Osservatore oggetto di cui ha bisogno dall'elenco.

Ottimizzazione :Se anche a mantenere le implementazioni ( quella vera + manichino ) vivo, in quanto l'Osservatore stesso, si può fare questo senza un effettivo blocco, e usare qualcosa come InterlockedExchangePointer per scambiare i puntatori.Worst case scenario :la delega di chiamata è in corso, mentre il puntatore viene scambiato --> no big deal tutti gli oggetti di rimanere in vita e di delega può continuare.Accanto delega chiamata sarà di nuovo l'attuazione dell'oggetto.( Salvo eventuali nuove riporti in corso )

Altri suggerimenti

Si potrebbe inviare un messaggio a tutti gli osservatori, informando l'origine dati è terminato e lasciare che gli osservatori rimuovere se stessi dalla lista.

In risposta al commento, l'attuazione di un soggetto osservatore modello dovrebbe dinamico per consentire l'aggiunta / rimozione di osservatori.In C#, il sistema di eventi è un soggetto/pattern observer in cui gli osservatori sono aggiunti utilizzando event += observer e rimosso utilizzando event -= observer.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top