le 10-29-2012 07:51 AM
En fichier attaché, un code simple illustrant un comportement bizarre lors de la lecture d'une variable partagée.
Le principe est que le VI "Communicateur1" écrit une valeur dans une variable partagée, attend une réponse du VI "Communicateur2" en détectant une valeur modifiée de la variable, puis reboucle.
Avec les sous-diagrammes activés par défaut dans les deux structures à diagrammes désactivés du VI "Communicateur1", tout fonctionne correctement. Mais j'ai eu quelques surprises à la mise au point 😞
Au démarrage du VI, la valeur courante de la variable partagée est considérée comme nouvelle. Pour que le VI se mette en attente d'une valeur modifiée dès la première exécution de la boucle While, il faut donc lire une première fois la variable partagée avant d'entrer dans la boucle. Jusque là, pas de problème...
En activant dans la boucle While le sous-diagramme avec un Timeout de -1, le programme fonctionne comme attendu, que la première lecture hors boucle soit faite sans Timeout ou avec un Timeout nul ou infini (-1). Cela semble indiquer que la valeur de la variable partagée n'est plus considérée comme nouvelle après lecture, quel que soit le mode de lecture. Or ce n'est pas ce qui se passe dans la boucle While !
Dans la boucle, le VI écrit une valeur dans la variable partagée puis la lit ; on s'attend donc à ce qu'il se mette en attente lors de la seconde lecture d'une valeur modifiée (qui doit constituer la réponse du VI "Communicateur2"). Mais si la première lecture après écriture est faite sans Timeout ou même avec un Timeout différent de -1, le VI ne s'arrête pas à la seconde lecture et boucle indéfiniment.
Une explication à ce fonctionnement étrange ?
Merci d'avance,
HL
10-31-2012 12:37 PM - modifié 10-31-2012 12:38 PM
Suite des bizarreries...
Résultats de tests avec le code attaché
Lecture sans timeout :
- La déconnexion provoque une erreur de lecture (et ici l'arrêt du programme) si une connexion à la variable partagée est ouverte ;
- En l'absence de connexion préalable, l'appel de la fonction ouvre automatiquement une connexion (et ici le programme continue à boucler malgré l'appui sur le bouton Stop).
Lecture avec timeout :
- L'erreur à la déconnexion (et ici l'arrêt du programme) a lieu avec ou sans connexion préalable.
- Si le timeout est infini (-1), la valeur de la variable au lancement du programme est vue comme nouvelle, donc la variable est lue une fois et le code s'arrête sur la boucle n°1, avec ou sans connexion préalable.
Sauf si la variable n'a pas été initialisée et est dans l'état "Aucune valeur connue" ; dans ce cas l'arrêt a lieu sur la boucle n°0.
- Si le timeout est nul, la valeur de la variable au lancement du programme est vue comme nouvelle seulement si une connexion a été préalablement ouverte (le programme boucle alors jusqu'à un appui sur Stop) ; sinon, le programme s'arrête dès la boucle n°0 (et non n°1 comme avec le timeout infini !) et attend une valeur modifiée.
- Si le timeout est non nul sans être infini, la valeur de la variable au lancement du programme est toujours vue comme nouvelle et le programme boucle jusqu'à un appui sur Stop.
Remarque :
La déconnexion "à distance" (diagramme désactivé dans la structure événement) ne fonctionne (et ici arrête le programme) que dans le cas d'une lecture avec timeout nul et sans ouverture de connexion avec la variable partagée !!!
Le moins qu'on puisse dire est que ce fonctionnement n'est pas intuitif et, sauf erreur de ma part, ce n'est pas documenté de façon précise dans l'aide de LabVIEW 😞
Bon week-end quand même 😉
HL
le 10-31-2012 05:00 PM
Autres tests de "déconnexion à distance"...
... avec encore des résultats pas franchement intuitifs (notamment sur les effets de l'ouverture ou non de la connexion à une variable) et, à ma connaissance, non documentés 😞
Dans le projet attaché :
- La seule différence entre les VIs "Variable" et "Variable PSP" est la classe sélectionnée dans le menu local du refnum de variable partagée.
Remarque : compte tenu des différences importantes que ce choix entraîne, il serait bien que quelque chose indique, sur le diagramme, la classe sélectionnée. Surtout que, dans les deux cas, l'identificateur de classe retourné par le noeud de propriété est le même !!!
- Selon la classe sélectionnée dans le VI "déconnexion", celui-ci arrête à distance le VI "Variable" ou "Variable PSP"... à condition qu'il n'y ait pas eu de connexion à la variable partagée (par le VI "Établir une connexion à une variable") dans le VI cible ; sinon, l'appel du VI "Fermer une connexion à une variable" dans le VI "déconnexion" ne produit rien !
- Aucun effet non plus si la classe sélectionnée dans le VI "déconnexion" est "Objet variable". Or c'est la classe sélectionnée par défaut si on crée une constante par un clic droit à partir du terminal "refnum de variable partagée en entrée" du VI "Fermer une connexion à une variable" ! D'où même remarque que plus haut sur l'intérêt d'une identification sur le diagramme de la classe sélectionnée.
En espérant que ces tests n'auront pas été utiles qu'à moi 😉
Re-bon week-end,
HL
le 11-28-2012 03:09 AM
le timeout est à 0 si vous ne cablez pas, il est donc normal que si on a pas -1 sur le timeout, une fois le temps écoulé il sort de la fonction et revient dessus au tour suivant.
petite note de l'aide sur labview:
![]()  | 
Attention Si vous utilisez cette fonction pour accéder à une variable partagée sans avoir d'abord ouvert une connexion à la variable, LabVIEW ouvre automatiquement une connexion à la variable. Cependant, cette opération d'ouverture implicite risque d'ajouter du jitter à l'application. Par conséquent, National Instruments vous recommande d'établir des connexions à toutes les variables avec la fonction Établir une connexion à une variable avant d'accéder aux variables. | 
le 11-28-2012 07:33 AM
Concernant l'ouverture ou non d'une connexion à une variable partagée, j'avais bien noté ce qu'indique l'aide de LabVIEW. Mais, justement, la note indique seulement un possible jitter en cas d'ouverture implicite alors qu'il y a d'autres effets, à ma connaissance non doumentés.
Illustration dans l'exemple joint (LabVIEW 2011), réduit à sa plus simple expression :
Si le programme est lancé en mode "Sans connexion", il s'arrête lorsqu'on clique sur "Déconnexion" ; en mode "Avec connexion", il ne s'arrête pas !
Comportement a priori pas évident... Ou ai-je râté quelque chose ?
HL
le 11-28-2012 08:19 AM
Salut,
As-tu vérifié en debug avec l'animation que dans le mode "Avec connexion", lorsque tu quittes sur "Déconnexion", tu ne resterais pas bloqué dans ta boucle de lecture qui a un timeout infini?
Cordialement.
le 11-28-2012 08:34 AM
Dans l'exemple joint au précédent message (et remis ici en pièce jointe), on peut aisément vérifier que le comportement est le même si le timeout est infini (-1) ou fini mais non nul.
Par contre le résultat d'un clic sur "Déconnexion" est différent selon que, au démarrage, la connexion a ou non été établie :
. "Sans connexion", la boucle While s'arrête sur une erreur provoquée par la déconnexion ;
. "Avec connexion", la déconnexion ne provoque pas d'erreur et la boucle continue.
HL
le 11-28-2012 09:25 AM
Bonjour,
Je viens de faire quelques essais avec ton dernier exemple. Tel quel, effectivement, dans le mode "Avec connexion" la déconnexion ne provoque pas d'erreur dans ta boucle de lecture.
Je viens d'essayer de nouveau en câblant la référence de variable partagéeissue de ta structure condition en entrée de ta fonction Fermer une connexion à une variable à la place de ta constante, et du coup, ça marche dans les 2 cas (voir VI ci-joint).
Visiblement, ton problème était du à un problème de référence.
Cordialement.
11-28-2012 10:19 AM - modifié 11-28-2012 10:20 AM
Effectivement, si tout est câblé, il n'y a pas de différence. Mais, idem, c'est une chose dont je n'ai pas vu qu'elle soit documentée quelque part !
Dans l'un des premiers messages du fil, je parlais de "déconnexion à distance" pour le cas où on opère la déconnexion en spécifiant la variable par une constante, dans un ensemble complètement séparé des opérations de lecture/écriture de la variable partagée. Évidemment, quand tout est dans un même VI, comme dans l'exemple, faire ainsi ne présente pas d'intérêt particulier. Par contre, une "déconnexion à distance" est utile pour arrêter, depuis un VI, des opérations de lecture/écriture d'une variable dans un ou plusieurs autres VIs (comme cela peut se faire en détruisant un notificateur ou une file d'attente ; c'est ce fonctionnement-là que je voulais reproduire avec les variables partagées... ce qui suppose donc de n'ouvrir que des connexions implicites dans les VIs où on lit ou écrit les variables partagées).
HL