IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

WinDev Discussion :

Le démarrage d'un thread ne se fait pas (aléatoire)


Sujet :

WinDev

  1. #1
    Membre habitué Avatar de elfasys
    Homme Profil pro
    Ingénieur automatismes industriels, conception et réalisation
    Inscrit en
    Octobre 2010
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur automatismes industriels, conception et réalisation
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2010
    Messages : 81
    Points : 144
    Points
    144
    Par défaut Le démarrage d'un thread ne se fait pas (aléatoire)
    Dans une installation de contrôle/commande d'une machine, avec 3 appareils principaux :

    - 1 PC windows XP, puis Seven depuis quelques semaines (appareil maître) et une application Windev 18
    - 1 automate programmable (type SAIA PCD3) appelé ici automate qui communique avec une liaison Ethernet
    - 1 microbalance à quartz (appelée ici STC) qui communique avec une liaison RS232

    j'ai un problème qui semble aléatoire concernant l'exécution d'un thread.

    L'automate est commandé et scruté par le PC (protocole propriétaire encapsulé dans un paquet IP et communication par socket : période de scrutation dans le cas de cet exemple : 0.8 seconde environ). On utilise le Thread_2_automate.

    Le STC est commandé et scruté par le PC (liaison série RS232 9600 bauds, période dans cet exemple période 4 secondes environ). On utilise le Thread_3_STC.

    Ce qui suit est un extrait d'un fichier historique, généré par l'application sur le PC

    Tous les événements liés à la communication avec le STC sont mémorisés.

    LE PROBLEME :

    De temps à autre (intervalle de temps de quelques heures, quelques jours ou quelques semaines, mais en général quelques jours) la procédure lancée par le code suivant (situé dans une procédure du thread principal et exécutée périodiquement) ne démarre pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Si ThreadEtat("Thread_3_stc") = threadInexistant ALORS ThreadExécute("Thread_3_stc",threadNormal,Acquisition_Stc)
    On ne va pas dans la première ligne de Acquisition_Stc et cela paralyse l'application. On le sait parce que dans cette première ligne se trouve le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Histo(''Acquisition_stc : première ligne de la procédure'')
    qui laisse une ligne dans l'historique quand elle est exécutée (exemple plus loin)

    Plusieurs configurations matérielles ont été essayées.
    Cela n'a aucune influence.

    La routine Histo qui génère tous les messages est la seule pouvant être lancée simultanément par tous les threads. Elle est protégée par un mutex

    Aucune action extérieure qui pourrait utiliser les mêmes ressources n'est utilisée (le problème peut survenir au milieu de la nuit, le week end, …)

    Pour la compréhension du texte, des lignes on été insérées dans l'historique pour les commentaires
    Deux lignes de code ont été insérées en exemple

    Il y a de nombreux messages parce qu'un mode de contrôle a été activé.
    La présence ou l’absence de ce mode de contrôle n'influe pas sur la présence ou l’absence de ce défaut.

    La période de scrutation n'intervient pas non plus :si on va plus vite, c'est l'appareil distant (le STC commandé et contrôlé par la liaison série) qui ne remplit plus d'autres fonctions dont il a la charge - d'ailleurs sans le signaler (autre problème...)


    EXTRAIT DE L'HISTORIQUE
    Séquence normale :

    .
    lignes précédentes. Puis :
    .
    .
    13/09/2013 ; 13:54:50 ; Ce message avait 6 caractère(s)
    13/09/2013 ; 13:54:50 ; Th_acquisition_stc : Demande de vie restante E7 : réponse en numérique retenue 97 pour 30 nécessaires
    13/09/2013 ; 13:54:50 ; Th_acquisition_stc : Quartz OK

    On passe ici au compte rendu de la commande suivante (commande F5)

    13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : Commande envoyée : F5
    13/09/2013 ; 13:54:50 ; Détail : 36 70 53 RC LF
    13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)
    13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
    13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse à la commande F5 : B1
    13/09/2013 ; 13:54:50 ; Détail : 36 66 49 RC LF
    13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)

    On passe ici au compte rendu de la commande suivante (commande F9)

    13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : Commande envoyée : F9
    13/09/2013 ; 13:54:50 ; Détail : 36 70 57 RC LF
    13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)
    13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
    13/09/2013 ; 13:54:50 ; Demande_dialogue_STC : réponse à la commande F9 : B6
    13/09/2013 ; 13:54:50 ; Détail : 36 66 54 RC LF
    13/09/2013 ; 13:54:50 ; Ce message avait 5 caractère(s)

    Cette ligne est la dernière ligne, correcte, générée par Demande_dialogue_STC à la fin de la procédure qui se termine et libère le thread.


    Suite de l'historique :

    13/09/2013 ; 13:54:57 ; Lecture sur l'automate
    13/09/2013 ; 13:54:57 ; Rafraîchissement synoptique
    13/09/2013 ; 13:54:59 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
    13/09/2013 ; 13:54:59 ; Lecture sur l'automate
    13/09/2013 ; 13:54:59 ; Rafraîchissement synoptique
    13/09/2013 ; 13:55:00 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
    13/09/2013 ; 13:55:00 ; Lecture sur l'automate
    13/09/2013 ; 13:55:00 ; Rafraîchissement synoptique
    13/09/2013 ; 13:55:01 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1


    DEBUT DE LA SEQUENCE NUMERO N*: ACQUISITION_STC
    ICI, FONCTIONNEMENT CORRECT

    La première ligne de code génère la ligne d'historique suivante, la deuxième lance effectivement la procédure.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Histo("Test pour le lancement de Acquisition_Stc : ThreadEtat('Thread_3_stc') = " + ThreadEtat("Thread_3_stc"))
    Si ThreadEtat("Thread_3_stc") = threadInexistant ALORS ThreadExécute("Thread_3_stc",threadNormal,Acquisition_Stc)
    13/09/2013 ; 13:55:01 ; Test pour le lancement de Acquisition_Stc : ThreadEtat('Thread_3_stc') = -1

    Les deux messages suivants sont normaux et viennent s'interposer ici (les différents threads sont asynchrones)*: le 1er est généré par le thread Thread_2_automate, le 2nd par le thread principal.

    13/09/2013 ; 13:55:01 ; Lecture sur l'automate
    13/09/2013 ; 13:55:01 ; Rafraîchissement synoptique

    Contrôle : on est entré dans la procédure Acquisition_Stc. Cette ligne d'historique est générée dans la première ligne de la procédure Acquisition_Stc, qui appelle immédiatement la procédure Th_acquisition_stc

    13/09/2013 ; 13:55:01 ; Acquisition_stc : première ligne de la procédure

    Contrôle : on est entré dans la procédure Th_acquisition_stc. Cette ligne d'historique est générée dans la première ligne de la procédure, qui va gérer les dialogues par la liaison série.

    13/09/2013 ; 13:55:01 ; Th_acquisition_stc : première ligne de la procédure

    Tout est correct.
    On passe ici au compte rendu de la première commande envoyée à l'appareil distant (le STC) (commande I89)

    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : I89
    13/09/2013 ; 13:55:01 ; Détail : 36 73 56 57 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 6 caractère(s)
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse à la commande I89 : B
    13/09/2013 ; 13:55:01 ; Détail : 36 66 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 4 caractère(s)

    On passe ici au compte rendu de la commande suivante (commande E1)

    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : E1
    13/09/2013 ; 13:55:01 ; Détail : 36 69 49 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus

    On passe ici au compte rendu de la commande suivante (commande E7)

    13/09/2013 ; 13:55:01 ; Th_acquisition_stc : Demande de vie restante E7 : réponse en numérique retenue 97 pour 30 nécessaires
    13/09/2013 ; 13:55:01 ; Th_acquisition_stc : Quartz OK

    On passe ici au compte rendu de la commande suivante (commande F5)
    On a fait un cycle complet depuis le début de cet exemple

    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : F5
    13/09/2013 ; 13:55:01 ; Détail : 36 70 53 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse à la commande F5 : B1
    13/09/2013 ; 13:55:01 ; Détail : 36 66 49 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)

    On passe ici au compte rendu de la commande suivante (commande F9)

    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : Commande envoyée : F9
    13/09/2013 ; 13:55:01 ; Détail : 36 70 57 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse complète terminée par les caractères de fin prévus
    13/09/2013 ; 13:55:01 ; Demande_dialogue_STC : réponse à la commande F9 : B6
    13/09/2013 ; 13:55:01 ; Détail : 36 66 54 RC LF
    13/09/2013 ; 13:55:01 ; Ce message avait 5 caractère(s)

    Le cycle se termine normalement. L'appareil distant (le STC) à répondu correctement et la séquence s'est terminée normalement.

    On continue :
    .
    .
    13/09/2013 ; 13:55:05 ; Lecture sur l'automate
    13/09/2013 ; 13:55:05 ; Rafraîchissement synoptique
    13/09/2013 ; 13:55:06 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1


    DEBUT DE LA SEQUENCE NUMERO N+1*: ACQUISITION_STC
    ICI, FONCTIONNEMENT DEFECTUEUX.


    13/09/2013 ; 13:55:06 ; Test pour le lancement de Acquisition_Stc : ThreadEtat('Thread_3_stc') = -1
    13/09/2013 ; 13:55:06 ; Lecture sur l'automate
    13/09/2013 ; 13:55:06 ; Rafraîchissement synoptique

    et plus rien ne se passe : on n'entre pas dans la procédure Acquisition_Stc, si on fait la moindre action (souris par exemple), on a le sablier.
    Le thread principal est bloqué
    C'EST LE DEFAUT.

    Après CTRL ALT SUP, on arrête l'application, on relance et tout redevient OK.

    Pas d'erreur système, pas d'erreur de l'application (sauf quand on cherche à la relancer : le système signale alors que l'appli est plantée)

    Redémarrage:

    13/09/2013 ; 14:02:55 ; Démarrage du programme.
    13/09/2013 ; 14:02:55 ; Répertoire programme : C:\Program Files (x86)\
    13/09/2013 ; 14:02:55 ; Répertoire privé : C:\ProgramData\Apsy11\Prive_APSY-E760-PC\
    13/09/2013 ; 14:02:55 ; Répertoire public réseau : C:\ProgramData\Apsy11\Data\
    13/09/2013 ; 14:02:55 ; Répertoire documentation : C:\ProgramData\Apsy11\Textes\
    13/09/2013 ; 14:02:55 ; Tentative d'ouverture de la liaison COM1
    13/09/2013 ; 14:02:55 ; Ouverture OK : paramètres COM1 9600 1 8 0
    13/09/2013 ; 14:02:55 ; Ouverture du port de communication 1 vers le STC OK.
    13/09/2013 ; 14:02:55 ; Le nouvel utilisateur courant est Jean François LEBRUN
    13/09/2013 ; 14:02:55 ; Test pour le lancement de Acquisition_automate : ThreadEtat('Thread_2_automate') = -1
    13/09/2013 ; 14:02:55 ; Lecture sur l'automate
    .
    .
    .
    etc.


    Quelqu'un a-t-il une intuition, pour une voie de recherche ?

    Le problème est-il suffisamment bien expliqué ?

  2. #2
    Membre émérite
    Homme Profil pro
    Développeur et responsable micros/réseaux
    Inscrit en
    Octobre 2010
    Messages
    1 286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur et responsable micros/réseaux
    Secteur : Bâtiment

    Informations forums :
    Inscription : Octobre 2010
    Messages : 1 286
    Points : 2 562
    Points
    2 562
    Par défaut
    Bonjour,

    à la lecture des log, je me demande si tu ne devrais pas tester que le thread 3 est bien redémarré lorsque tu le relances. Est-ce déjà le cas ?

    à bientôt,

    Nicolas

  3. #3
    Membre habitué Avatar de elfasys
    Homme Profil pro
    Ingénieur automatismes industriels, conception et réalisation
    Inscrit en
    Octobre 2010
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur automatismes industriels, conception et réalisation
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2010
    Messages : 81
    Points : 144
    Points
    144
    Par défaut
    Bonjour, et merci...

    Ce que tu proposes indiquera peut-être quelque chose.
    J'ajoute ceci dans une procédure périodique existante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Histo_STC("Test pour la vérification de l'état du Thread_3_stc : Etat = " + ThreadEtat("Thread_3_stc"))
    J'ai déjà introduit une autre modif : j'utilise maintenant une fonction spéciale Histo_STC(<message>) qui est un copier/coller de ma fonction habituelle Histo(<message> avec des variables globales et un fichier différent, et qui n'est utilisée que dans ce Thread_3_stc.

    J'évite donc le risque d'exécution simultanée du code - et donc l'usage d'un mutex.

    J'installe tout cela chez le client... et j’attends le prochain plantage, dans 1 heure, dans 1 jour, dans une semaine, ou jamais... (ce qui serait finalement déprimant !)

  4. #4
    Membre habitué Avatar de elfasys
    Homme Profil pro
    Ingénieur automatismes industriels, conception et réalisation
    Inscrit en
    Octobre 2010
    Messages
    81
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 78
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur automatismes industriels, conception et réalisation
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2010
    Messages : 81
    Points : 144
    Points
    144
    Par défaut
    Bonjour

    Au bout d'une semaine, le défaut est réapparu.

    Je vais essayer de la décrire autrement.

    Dans une application (décrite autrement dans les posts précédents), j'ai deux procédures lancées périodiquement.

    La première est une procédure locale à la première fenêtre (période environ 0.5 secondes. C'est une fonction de mise à jour de champs et de libellés en fonction de variables globales)

    La deuxième est une procédure globale au projet (période de l'ordre de 0.8 secondes. C'est une fonction de lancement de threads pour gérer l'acquisition des variables physiques d'une installation industrielle - températures, pressions, états mécaniques, vitesses... - ceci par une liaison série (pour un appareil dans un thread réservé) et par une liaison socket (pour un autre appareil dans un autre thread).

    J'ai de nombreux messages qui enregistrent les événements et qui m'indiquent que tout se passe bien, sauf que... périodiquement, l'appli semble être plantée. Ces deux procédures, lancées par des timers (TimerSys) indépendants semblent ne plus être relancées, ce qui bloque aussi les événements souris, clavier, etc.

    Je fais CTRL ALT DEL, j'arrête l'application, je redémarre et tout est OK pour quelque temps.

    Je n'ai plus aucune idée... C'est la déprime.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    303
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 303
    Points : 815
    Points
    815
    Par défaut
    Bonjour elfasys,

    Citation Envoyé par elfasys Voir le message

    Dans une application (décrite autrement dans les posts précédents), j'ai deux procédures lancées périodiquement.

    ...

    La deuxième est une procédure globale au projet (période de l'ordre de 0.8 secondes. C'est une fonction de lancement de threads pour gérer l'acquisition des variables physiques d'une installation industrielle - températures, pressions, états mécaniques, vitesses... - ceci par une liaison série (pour un appareil dans un thread réservé) et par une liaison socket (pour un autre appareil dans un autre thread).

    ...
    C'est la déprime.
    Je vais juste te parler des threads d'acquisition.
    Ils devraient démarrer avec l'application, une fois pour toute, et s'arrêter avec l'application.

    Pourquoi les relancer par un Timer ?

    Si tu as besoin d'un délai entre 2 acquisitions, le plus simple est que le thread fasse une pause.
    Pour ça, tu peux utiliser la fonction ThreadPause.
    http://doc.pcsoft.fr/fr-fr/?3077029&...pause_fonction

    Qu'en penses-tu ?

Discussions similaires

  1. Thread + component + Refresh qui ne se fait pas
    Par superdaok84 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 23/01/2008, 17h57
  2. [Thread] PB Thread.sleep(1000) marche pas
    Par kliel dans le forum Concurrence et multi-thread
    Réponses: 6
    Dernier message: 03/12/2004, 14h47
  3. Int 21H AX=716Ch ne fait pas mon affaire !!
    Par TheBigMac dans le forum Assembleur
    Réponses: 4
    Dernier message: 10/09/2004, 21h51
  4. Pb de selection qui ne se fait pas
    Par Stef.proxi dans le forum Langage SQL
    Réponses: 4
    Dernier message: 06/08/2004, 11h54
  5. [SQL Server 8] le join ne se fait pas
    Par Baquardie dans le forum Langage SQL
    Réponses: 10
    Dernier message: 29/07/2004, 15h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo