1

Dans un système d'acquisition de signaux numériques, les données sont souvent transmises à un observateur dans le système par un thread.Modèle de conception pour les observateurs multithread

exemple de Wikipedia/Observer_pattern:

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

Lorsque par exemple, une action de l'utilisateur par exemple un thread GUI nécessite que les données s'arrêtent de couler, vous voulez rompre la connexion sujet-observateur, et même disposer de l'observateur tout à fait.

On peut argumenter: vous devriez juste arrêter la source de données, et attendre une valeur sentinelle pour disposer de la connexion. Mais cela entraînerait plus de latence dans le système.

Bien sûr, si le thread de pompage de données vient de demander l'adresse de l'observateur, il peut trouver qu'il envoie un message à un objet détruit.

Quelqu'un a-t-il créé un motif de conception «officiel» pour contrer cette situation? Ne devraient-ils pas?

+0

Je suis un peu confus ici. Qu'est-ce que vous essayez d'éviter?Parlez-vous d'un cas où un thread veut désinscrire un observateur, mais un autre thread itérer sur tous les observateurs? –

+0

Je ne sais pas dans quelle classe concrète vous avez implémenté 'IObserver' mais si" Update "veut dire" faites tout ce que vous devez faire pour vous mettre à jour avec une source de données ", alors le comportement correct pour un objet disposé serait de ne rien faire en silence. Si un objet associé à chaque observateur indique s'il doit continuer à recevoir des abonnements et si l'objet de pompage possède un indicateur indiquant si ces objets ont demandé une désinscription depuis leur dernière analyse, le thread de pompage peut interroger les objets pour les désabonnements. si nécessaire. – supercat

Répondre

2

Si vous voulez que la source de données soit toujours du bon côté de la simultanéité, vous devez avoir au moins un pointeur toujours sûr pour lui. L'objet Observateur doit donc avoir une durée de vie qui n'est pas terminée avant celle de la source de données. Ceci peut être fait en ajoutant seulement des observateurs, mais en ne les supprimant jamais. Vous pouvez demander à chaque observateur de ne pas effectuer lui-même l'implémentation principale, mais de déléguer cette tâche à un objet ObserverImpl. Vous verrouillez l'accès à cet objet impl. Ce n'est pas grave, cela signifie simplement que le désabonnement GUI sera bloqué pendant un petit moment au cas où l'observateur est occupé à utiliser l'objet ObserverImpl. Si la réactivité de l'interface graphique est un problème, vous pouvez utiliser une sorte de mécanisme de file d'attente concurrente avec un job de désabonnement. (comme PostMessage sous Windows)

Lors de la désinscription, vous remplacez simplement l'implémentation principale par une implémentation fictive. Encore une fois cette opération devrait saisir le verrou. Cela introduirait en effet un peu d'attente pour la source de données, mais puisqu'il s'agit juste d'un [swap-pointer swap-unlock] vous pourriez dire que c'est assez rapide pour les applications en temps réel. Si vous voulez éviter d'empiler des objets Observer qui contiennent juste un mannequin, vous devez faire une sorte de comptabilité, mais cela pourrait se résumer à quelque chose de trivial comme un objet contenant un pointeur sur l'objet Observateur dont il a besoin dans la liste . Si vous gardez aussi les implémentations (la vraie + le mannequin) en vie aussi longtemps que l'Observateur lui-même, vous pouvez le faire sans un verrou réel, et utilisez quelque chose comme InterlockedExchangePointer pour échanger les pointeurs. Scénario le plus défavorable: l'appel de délégation se poursuit pendant que le pointeur est échangé -> ce n'est pas grave, tous les objets restent actifs et la délégation peut continuer. L'appel de délégation suivant sera un nouvel objet d'implémentation. (À moins de nouveaux swaps bien sûr)

0

Vous pouvez envoyer un message à tous les observateurs pour les informer que la source de données se termine et laisser les observateurs se retirer de la liste.

En réponse au commentaire, l'implémentation du modèle sujet-observateur devrait permettre l'ajout/le retrait dynamique d'observateurs. En C#, le système d'événements est un modèle sujet/observateur où les observateurs sont ajoutés en utilisant event += observer et supprimés en utilisant event -= observer.

+0

En effet, mais l'idée est que la source de données continue de fonctionner (car elle a par exemple un temps de configuration énorme ...), et vous vous désinscrivez à la volée. – xtofl

Questions connexes