Pergunta

Em um sistema de aquisição de sinal digital, muitas vezes os dados são enviados para um observador no sistema por um thread.

exemplo de Wikipédia/Observer_pattern:

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

Quando, por ex.uma ação do usuário de, por exemplo,um thread GUI exige que os dados parem de fluir, você deseja interromper a conexão sujeito-observador e até mesmo descartar o observador por completo.

Alguém pode argumentar:você deve apenas interromper a fonte de dados e aguardar que um valor sentinela descarte a conexão.Mas isso incorreria em mais latência no sistema.

É claro que, se o encadeamento de bombeamento de dados acabou de solicitar o endereço do observador, ele poderá descobrir que está enviando uma mensagem para um objeto destruído.

Alguém criou um padrão de design 'oficial' para combater essa situação?Não deveriam?

Foi útil?

Solução

Se você quer ter a fonte de dados para estar sempre no lado seguro da concorrência, você deve ter pelo menos um ponteiro que é sempre mais seguro para ele usar. Assim, o objeto Observer deve ter uma vida que não é terminado antes que da fonte de dados.

Isto pode ser feito apenas por adição de observadores, mas nunca retirá-los. Você poderia ter cada observador não a própria aplicação core, mas tem que delegar essa tarefa a um objeto ObserverImpl. Você bloquear o acesso a este objeto impl. Este não é um grande negócio, isso significa apenas o GUI unsubscriber seria bloqueado por pouco tempo no caso do observador está ocupado usando o objeto ObserverImpl. Se GUI resposta seria um problema, você pode usar algum tipo de mecanismo de trabalho de fila em simultâneo com um trabalho unsubscription empurrou para ele. (Como PostMessage em Windows)

Quando cancelar, basta substituir a implementação de núcleo para uma implementação fictícia. Mais uma vez esta operação deve agarrar a fechadura. Esta seria, de fato introduzir algum espera para a fonte de dados, mas já que é apenas um [bloqueio - ponteiro de swap - desbloqueio]. Você poderia dizer que este é rápido o suficiente para aplicações em tempo real

Se você quer evitar empilhamento Observer objetos que contêm apenas um manequim, você tem que fazer algum tipo de contabilidade, mas isso poderia resumir-se a algo trivial como um objeto segurando um ponteiro para o objeto Observer que ele precisa da lista.

Optimization: Se você também manter as implementações (o real + o manequim) vivo, enquanto o próprio observador, você pode fazer isso sem um bloqueio real, e usar algo como InterlockedExchangePointer para trocar os ponteiros. Pior cenário: chamada delegando está acontecendo enquanto ponteiro é trocado -> não é grande coisa todos os objetos permanecer vivo e delegar pode continuar. chamada de delegação próxima será a de novo objeto de implementação. (Restrição de quaisquer novos swaps de curso)

Outras dicas

Você pode enviar uma mensagem para todos os observadores, informando-os da fonte de dados está sendo finalizado e deixar os observadores retirar-se da lista.

Em resposta ao comentário, a implementação do padrão sujeito-observador deve permitir a dinâmica adição / remoção de observadores. Em C #, o sistema de eventos é um padrão sujeito / observador onde os observadores são adicionados usando event += observer e removido usando event -= observer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top