Partage intempestif de variables statiques entre deux instances. [Résolu]

Signaler
Messages postés
5
Date d'inscription
mercredi 21 février 2007
Statut
Membre
Dernière intervention
26 mars 2008
-
g_clairet_2
Messages postés
5
Date d'inscription
mercredi 21 février 2007
Statut
Membre
Dernière intervention
26 mars 2008
-
Bonjour,


Je suis en stage et ça fait que 4 mois que je débute sur vb6. Je dois faire une appli qui lance une deuxième instance d’elle-même au démarrage.
Ça, ça marche . Mon soucis est que j’ai des variables statiques dans une fonction qui ne s’initialise pas ou qui prend la valeur fixée dans l’autre instance .


Comment puis-je faire pour éviter ce partage (si c’est ça) ou être sur de l’initialisation de mes variables.
Il y a-t-il une manière de faire pour que les variables d’une instance soient locales à cette instance ? Et partagées entre instance (ça peut aussi me servir de piste).

Nota :
   - Elles sont modifiées par un seconde fonction par un passage de référence.
   - Je développe pour Win 98 (imposé par le stage).


Merci d’avance pour votre aide.

8 réponses

Messages postés
5
Date d'inscription
mercredi 21 février 2007
Statut
Membre
Dernière intervention
26 mars 2008

Bonjour,
Oulala, ça fait longtemps.

Bon, première chose, je tiens à m'excuser d'avoir laissé ce forum sans nouvelles, j'avais perdu tout mes passwords sur l'ordi sur lequel je travaillais et (je ne sais pas pourquoi) le lien pour recevoir les passwords oubliés ne m'envoyait rien. Donc, c'est par le plus grand des hazards que je me remet un peu à la prog et que je retrouve mes mots de passe (je vais vite le noter quelque part celui-là).

Deuxième chose, comme je ne veux pas laisser le suspence durer plus longtemps, je me suis replongé dans mes archives et voici les causes supposées et les corrections apportées :

0) Je replace le contexte : je devais faire un banc de test pendant un stage. Ce qui incluait le développement Hardware et Software. Je passe sous silence le Hardware. Le programme devait permettre de vérifier diverses fonctionnalitées des appareils à tester et disposait d'une carte d'acquisition analogique/numérique pour mesurer les données physiques, d'une carte de commande de relais (interrupteur commandés par ordinateur) etr d'une communication RS232.
Le problème : le programme de test doit se lancer en 2 instances indépendantes pour gérer les 2 puits de test (en fait c'est un banc double). Quand un seule des instances est utilisées à la fois, pas de problèmes mais dès que les 2 instance tournent conjointement, des données d'acquisition addressées à l'instance (1) semblent être transmises également à l'instance (2) sans que cela ne soit voulu et sans pouvoir y remédier. Nécessité de redémarrer l'ordinateur du banc pour retrouver un fonctionnement normal qui ne durera qu'un temps.
Différentes solutions ont été proposées plus haut pour corriger ceci mais le problème reste. Donc voici mes solutions :


1) Correction de la fonction faisant l'interface entre le coeur du programme et la carte d'acquisition analogique/numérique PCI. En effet, pour permettre un maximum de flexibilité de cette fonction, je ré-activais (identifiais) la carte à chaque commande que je lui transmettais. Résultat, ma frèquence d'acquisition réelle était médiocre comparé au spécification du constructeur de la carte. Après avoir discuté avec le constructeur et fait un petit contrôle de chronomètrage basé sur l'horloge CPU,  j'ai modifié la fonction pour qu'elle n'active la carte que quand c'est nécessaire (plusieurs cartes installées) et j'ai gagné un facteur temporel de 2000 . Je ne m'étais pas rendu compte de ces latences parasites sous Win98. C'est un passage sous XP qui m'a permis de tout découvrir. c'est quand même mieux XP .

2) Découverte de l'utilisation de l'insruction DoEvent(). Donc ré-écriture de tout le code pour l'alléger et supprimer le super-méga-compliqué mécanisme de transfert de paramètres entre les différents modules et sous-programmes. J'utilisais un Label (ou un truc comme ça, je me rappelle plus bien) dans les propriétés du seul et unique timer du programme pour transmettre le contexte et l'étape d'exécution du programme. Le timer servait pour donner le délais de traitement des interruptions système.
J'explique (attention c'est compliqué), ma philosophie à ce moment était similaire à celle d'un programmateur temps réel : à intervale réguliers, je rends la main  au coeur (l'interface graphique pour moi) pour pouvoir traiter les interruption de la connection RS232 (et oui, il y avait ça aussi). Donc je rentre dans le sous-programme, j'exécute un bout, je sors, je traite mes interruptions, je re-rentre, je continu, je re-sors, etc... et à chaque sortie, je perds toutes mes variables ainsi que l'étape de la fonction en cours (pas de variables globales ni publiques, des fonctions indépendantes et les poules sont bien gardées). Il fallait trouver un moyen de récupérer ces variables. Et bien je les stockais tout simplement dans le Label accroché à la patte du timer sous forme de chaine de caractères.
Je vous raconte pas la tête du truc quand on passe par 3 couches de sous-programmes avec chacun leur contexte à sauvegarder et les infos à transmettre, etc... j'avais même dût dessiner le mécanisme pour m'y retrouver et encore, ça restait compliqué.
Donc exit le mécanisme super-méga-compliqué et on fait du nettoyage. Supprime le timer et son Label, supprime les commandes d'écriture dans le Label, supprime tout le bazard pour retrouver quel sous-programme s'exécutait et où il en était. Ré-ecriture de tout le code pour faire des boucles dans les sous-programmes et fonctions avec utilisation de DoEvent().
Résultat : un code plus léger, plus facile à lire (et à reprendre), une exécution plus rapide et plus fiable, un ensemble plus stable et un (tout petit) peu moins de mémoire consommée .

Ne ne sais pas exactement laquelle de ces correction à porté ses fruits. Je pense que le mécanisme super-méga-compliqué devait plus noyer le poisson et charger inutilement le processeur. Je pencherais plus pour la solution de la modification de la fonction d'interfaçage avec la carte d'acquisition et du passage à XP. Il serait possible que, sous Win98, je demandais d'exécuter trop rapidement des acquisition. Résultat, il stockait les demandes dans un buffer et au final, le driver de la carte ne savait plus à qui il devait envoyer les résultats et continuait de traiter la (très) longue liste de demande en attente, d'où le bloquage .

En clair, faites pas comme moi, apprenez un langage avant de commencer un stage où on vous largue dans l'autonomie quasi-complète. Surtout si le sujet est compliqué. Et pensez aussi à bien vous renseigner sur les périphériques que vous utilisez quite à téléphoner au fabriquant. Dans mon cas, il n'était indiqué nul part que cette instruction d'activation de la carte prenait 100 ms alors que toutes les autre ne prenait que 50 µs . Et développer sur un OS comme Win98, voila un autre mauvais choix. Il est trop permissif pour cette utilisation.
Quoi que, au moins, j'aurais appris plein des choses en tombant dans toutes les chausse-trappes de ce projet et en plus j'ai eu droit à une offre d'emploi à la fin .

En tout cas merci à tous ceux qui m'ont apporté leur aide et j'espère ne pas vous avoir endormis avec la tartine que je vous sers.

Ce sujet est maintenant clos.
Messages postés
15815
Date d'inscription
jeudi 8 août 2002
Statut
Modérateur
Dernière intervention
4 mars 2013
93
Deux instances d'une application partage des variables ??? C'est risqué cà !

A la limite, tu peux déclarer tes variables statiques en private au niveau du module (donc pour une classe, déclarer la variable en private au niveau classe), ainsi elle aura le même comportement qu'une variable statique (ou presque).
Messages postés
13298
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
30
salut,
où utiliser Command$, la 1ère appli donnant alors les arguments à sa 2e instance au lancement

(enfin, si j'ai bien compris la demande...)
++
<hr size="2" width="100%" />Prenez un instant pour répondre à [infomsg_SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp
Messages postés
5
Date d'inscription
mercredi 21 février 2007
Statut
Membre
Dernière intervention
26 mars 2008

Bonjour,
premièrement merci d'avoir répondu aussi vite. Pour un premier post je ne savais pas trop ce que ça allait donner.

Ensuite, petites précisions :
   Mes fonctions sont dans un module et je peux pas trop changer parce que je ne connais pas assez les classes et que j'ai déjà 2 mois de retard sur mon projet. (Ceci dit en parlant de classe, la fonction CallByName est amusante.)

   Je décris rapidement le logiciel sans entrer dans les détails. Le logiciel ce lance et vérifie qu'il n'y a pas d'autre instance d'ouverte. Si c'est le cas, il se place à gauche de l'écran et lance une seconde instance (Fonction Shell()) avec pour argument la position de la fenêtre à droite (comme tu l'indiquais PCPT). Dans le cas contraire, l'instance s'ouvrant va ce placer dans l'espace libre. J'interdis l'ouverture de plus de 2 instances en même temps.
Je crois que j'avais trouvé les infos pour l'auto-lancement dans un des posts ou tutos.

   Le soucis que j'ai est que je lance la fonction sur la première instance, elle m'initialise des variables statiques, c'est bon (note : l'initialisation est faite à partir des données renvoyées par une carte PCI d'acquisition analogique-numérique). Je recommence, toujours bon. Je lance cette même fonction sur la deuxième instance, elle initialise ses variables statiques, c'est bon. Je relance la fonction de la première instance. Les variables semblent s'initialiser (c'est ce que m'affiche le Debug.Print) mais les valeurs prises en compte pour le traitement suivant sont celles fixées par la deuxième instance. Et là plus moyen d'initialiser quoi que ce soit à moins de re-démarrer l'ordi.

   Je viens de tenter une modification, les variables étaient définies statiques dans une fonction normale public, elle sont maintenant normales ("Dim") dans une fonction public statique. Je vous tiens au courant si ça change quelque chose.

Heu question Darksidious, comment tu définis une variable static en private ? Pas pensé à ça, je vais essayer.

Je vous tiens au courant.
Messages postés
15815
Date d'inscription
jeudi 8 août 2002
Statut
Modérateur
Dernière intervention
4 mars 2013
93
Lol je te disais pas de déclarer en Static ET private, mais de la déclarer uniquement Private au niveau module, et non plus Static au niveau function.
Messages postés
5
Date d'inscription
mercredi 21 février 2007
Statut
Membre
Dernière intervention
26 mars 2008

Bonjour,

le projet est mis en attente, il faut que je rédige mon rapport de stage et préparer ma soutenance (faire le rapport avant la fin du stage, j'vous jure ça veut rien dire). je vous préviens quand je m'y remet.

à bientot.
Messages postés
5
Date d'inscription
mercredi 21 février 2007
Statut
Membre
Dernière intervention
26 mars 2008

Bonjour,

bon ça y est la soutenance est passée, le rapport rendu, je peux me remettre au travail.

Alors Darksidious, je vais essayer ta méthode mais je la comprend pas très bien. Si je déclare mes variables en private au niveau module, est-ce que je conserve les valeurs même si je sors du module??
C'est un peu ce que fait mon programme : je rentre, j'exécute un bout de ma fonction, je sorts, je re-rentre, je continu, je re-sors, etc ...

Ce que je comprend pas c'est pourquoi une instance va modifier des valeurs définies dans une autre instance et pourquoi je ne peux pas les ré-initialiser.
Messages postés
15815
Date d'inscription
jeudi 8 août 2002
Statut
Modérateur
Dernière intervention
4 mars 2013
93
Ben ce qui fait peur surtout, c'est que deux instances de ton prog utilise les mêmes variables ! Je te raconte pas les problèmes que cela peut provoques (la preuve !), c'est vraiment très étonnant !!!

Au niveau module, tes variables ont une durée de vie qui dure tout le long de l'éxécution de ton programme : comme les static dans tes fonctions en fait, par contre, fait bien attention de les nommer différement si tu les utilise dans deux fonctions différents avec un but différent !