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

C++Builder Discussion :

Problème d'affichage de signaux à l'écran


Sujet :

C++Builder

  1. #21
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Alors voilà mon Thread après modification

    Dans le .h en public
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    // Mode
    int Mode;
     
    // Temps de stim
    int TempsStim;
     
    // Temps
    int Temps;
    Mode peut avoir comme valeur les constantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // Constante pour le Mode
    #define FIN 0
    #define ATTENTE 1
    #define SIGNAL 2
    Fonction Execute et la fonction ModeSignal que je lance pour lancer une attente
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
     
    // Méthode qui met le Thread en Mode SIGNAL
    void __fastcall MonThread::ModeSignal(int TpsStim, int Tps)
    {
    	// On renseigne les valeur de TempsStim et de Temps
    	TempsStim = TpsStim;
    	Temps = Tps;
     
    	// On passe le Thread en Mode Signal
    	Mode = SIGNAL;
    }
     
    //---------------------------------------------------------------------------
     
    // Méthode qui gère l'exécution du Thread
    void __fastcall MonThread::Execute()
    {
    	// Tant que le Thread n'est pas en Mode Fin
    	while(Mode != FIN)
    	{
    		// Selon le Mode
    		switch(Mode)
    		{
    			// Si l'on est en Mode Attente
    			case ATTENTE :
    			{
    				// On ne fait rien
    				Sleep(0);
     
    				break;
    			}
     
    			// Mode SIGNAL
    			case SIGNAL :
    			{
    				// S'il y a une Stim
    				if(TempsStim != -1)
    				{
    					// Si le temps de Stim est supérieur à 0
    					if(TempsStim > 0)
    					{
    						Sleep(TempsStim);
    					}
     
    					// On envoi le Signal à la Caret E/S
    				}
     
    				// Si Le Mode n'est pas passé à Fin
    				if(Mode != FIN)
    				{
    					// On va calculer le temps restant pour l'attente
    					int TempsRestant;
     
    					// S'il y a eu une Stim
    					if(TempsStim != -1)
    					{
    						// On calcule le Temps qu'il reste avant la Fin
    						TempsRestant = Temps - TempsStim;
    					}
    					// Sinon il n'y a pas eu de Stim
    					else
    					{
    						// Le Temps restant correspondant au Temps
    						TempsRestant = Temps;
    					}
     
    					// On se met en attente
    					Sleep(TempsRestant);
     
    					// On passe en Mode ATTENTE
    					Mode = ATTENTE;
    				}
    			}
     
    			break;
    		}
    	}
    }
    Le Thread au départ est initialisé avec le Mode ATTENTE.

    Là j'ai une charge beaucoup moins importante par contre lorsque je veux interrompre (appuie sur Echap qui fait passer le Mode à FIn), le Thread ne s'arrête pas immédiatement mais à la fin de l'attente en cours. J'aurais préférer pouvoir effectuer l'interruption immédiatement

  2. #22
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    Ta gestion du temps restant aurait peu être simplifié en jouant sur un Sleep(TempsAttente)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    // Méthode qui gère l'exécution du Thread
    void __fastcall MonThread::Execute()
    {
      int TempsAttente = 0;
        // Tant que le Thread n'est pas en Mode Fin
      while(Mode != FIN)
      {
        // Selon le Mode
        switch(Mode)
        {
          // Si l'on est en Mode Attente
          case ATTENTE :
          {
            // On ne fait rien
            Sleep(TempsAttente);
            TempsAttente = 0;
     
            break;
          }
     
          // Mode SIGNAL
          case SIGNAL :
          {
            // S'il y a une Stim
            if(TempsStim != -1)
            {
              // Si le temps de Stim est supérieur à 0
              if(TempsStim > 0)
              {
                Sleep(TempsStim);
              }
     
              // On envoi le Signal à la Caret E/S
            }
     
            // Si Le Mode n'est pas passé à Fin
            if(Mode != FIN)
            {
              // On va calculer le temps restant pour l'attente
              // S'il y a eu une Stim
              if(TempsStim != -1)
              {
                // On calcule le Temps qu'il reste avant la Fin
                TempsAttente = Temps - TempsStim;
              }
              // Sinon il n'y a pas eu de Stim
              else
              {
                // Le Temps restant correspondant au Temps
                TempsAttente = Temps;
              }
     
              // On passe en Mode ATTENTE
              Mode = ATTENTE;
            }
          }
     
          break;
        }
      }
    }

    Citation Envoyé par kurul1 Voir le message
    (appuie sur Echap qui fait passer le Mode à FIn), le Thread ne s'arrête pas immédiatement mais à la fin de l'attente en cours. J'aurais préférer pouvoir effectuer l'interruption immédiatement
    Remplace Sleep par un TEvent.WaitFor (objet encapsulant API CreateEvent\WaitForSingleObject)
    Tu pourras ainsi faire un SetEvent pour arrêter le WaitFor pour un arrêt plus rapide !
    D'ailleurs aucune gestion de TThread.Terminate() ni Terminated !
    Étrangement codé tout ça !

    D'ailleurs, une gestion totale par TEvent pour signaler une "Stim" serait bien plus élégant
    ModeSignal faisant un SetEvent pour "réveiller" le thread

    Je suppose que tu as retire beaucoup de code lié à ton dialogue, cela difficile de comprendre comment fonctionne réellement ton thread !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    //---------------------------------------------------------------------------
    /*constructor*/__fastcall MonThread::MonThread(...)
      : TThread(?), 
        ...
    {
      FEvent = new TEvent(NULL, false, false, "", false); // AutoReset !
    }
     
     
    //---------------------------------------------------------------------------
    // Méthode qui met le Thread en Mode SIGNAL
    void __fastcall MonThread::ModeSignal(int TpsStim, int Tps)
    {
      // On renseigne les valeur de TempsStim et de Temps
      TempsStim = TpsStim;
      Temps = Tps;
     
      // On passe le Thread en Mode Signal
      FEvent.SetEvent();
      Mode = SIGNAL;
    }
     
    //---------------------------------------------------------------------------
    // Méthode qui met le Thread en Mode FIN
    void __fastcall MonThread::ModeFin()
    {
      // On passe le Thread en Mode Fin
      Terminate();
      FEvent.SetEvent();
    }
     
    //---------------------------------------------------------------------------
    // Méthode qui gère l'exécution du Thread
    void __fastcall MonThread::Execute()
    {
      // Tant que le Thread n'est pas en Mode Fin
      while( ! Terminated)
      {
        TWaitResult wr = FEvent.WaitFor(INFINITE);
     
        if ( ! Terminated && (wr == wrSignaled))
        {
          // S'il y a une Stim
          if(TempsStim != -1)
          {
            // ???? Tu es obligé d'attendre, un temps précis pour répondre !
     
            // Si le temps de Stim est supérieur à 0
            if(TempsStim > 0)
              Sleep(TempsStim);
     
            // On envoi le Signal à la Carte E/S
            ... là je suppose que tu as un objet qui dialogue !
          }
     
          break;
        }
      }
    }
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #23
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Je n'ai pas mis de Terminate() car quand je crée mon Thread je met ceci après la ligne du New

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	Thread->FreeOnTerminate = true;
    Je pensais que cette ligne faisait le nettoyage dès que la méthode Execute se termine. Je me trompe ?

    Pour le dialogue avec la Carte d'E/S, j'ai une classe que j'ai écrite qui gère l'envoi et la réception de données de la carte, je n'ai pas jugé nécessaire de faire apparaitre le code ici vu que ce n'était pas le sujet de ma question.

  4. #24
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 455
    Points : 24 867
    Points
    24 867
    Par défaut
    Citation Envoyé par kurul1 Voir le message
    Je n'ai pas mis de Terminate() car quand je crée mon Thread je met ceci après la ligne du New

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	Thread->FreeOnTerminate = true;
    Je ne vois pas le rapport, c'est justement Terminate() qui permet de contrôler la boucle du Execute(), une fois sortie de la boucle, en fonction de FreeOnTerminate cela va libérer le thread automatiquement

    FreeOnTerminate t'évite l'appel d'un delete mais en aucun cas cela t'évite l'appel à Terminate() !

    Citation Envoyé par kurul1 Voir le message
    Je pensais que cette ligne faisait le nettoyage dès que la méthode Execute se termine. Je me trompe ?
    Non, tu as compris mais c'est juste que ta boucle Execute() ne respectent pas conventions d'implémentation du TThread qui DOIT tester Terminated !
    Ne confond pas Terminate() appelé de l'extérieur qui passe à false la valeur de la propriété Terminated.

    Extrait de l'aide :
    Surchargez Execute et insérez le code à exécuter quand le thread commence. Execute doit tester la valeur de la propriété Terminated afin de déterminer s'il faut sortir du thread.
    Tu utilises FreeOnTerminate alors qu'à tout moment on peut appeler MonThread::ModeSignal sur l'objet thread libéré, ce n'est pas prudent, tu pourrais donc avoir un thread libéré automatiquement et un appel à ModeSignal !
    Tu conserves dans ton programme une référence sur l'instance TThread, cette référence à un moment donné peut pointer sur une zone mémoire libérée
    Tu peux gérer un OnDestroy pour "effacer" la référence en lui affectant NULL pour protéger l'appel à MonThread::ModeSignal mais le mieux c'est de faire un delete explicite après une séquence genre Mode Fin\Terminate\WaitFor

    Peut-être que ton code ne le permet pas actuellement mais c'est encore une fois en contradiction avec les bonnes pratiques :

    Extrait de l'aide :
    Quand FreeOnTerminate a la valeur true, la méthode Execute doit exécuter puis libérer le thread avant que votre application puisse exécuter la ligne de code suivante. Donc, vous ne devez appeler aucune méthode de l'objet thread quand FreeOnTerminate a la valeur true sauf si vous créez le thread dans un état suspendu

    ...

    Dans l'éventualité où vous voudriez communiquer avec les threads ou interagir avec eux de toute autre manière, y compris leur dire quand s'achever, FreeOnTerminate ne doit jamais être utilisée.

    Citation Envoyé par kurul1 Voir le message
    je n'ai pas jugé nécessaire de faire apparaitre le code ici vu que ce n'était pas le sujet de ma question.
    un pseudo code genre TDialogue.Send() ou TDialogue.Recv() aurait permis de mieux cerné ton problème, tu nous fourni un code tronqué qui ne fait rien, cela complique la compréhension car l'on doit deviner comment ton code fonctionne

    Par exemple, on ignore comment fonctionne objet dialogue, bloquant ou asynchrone, dans une approche thread, les détails comme cela comptent !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #25
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Merci pour les explications pour FreeOnTerminate et Terminate, je n'avais pas compris cela comme ca donc pas étonnant que dans mon ancienne version cela explose la mémoire vu que je ne les terminait pas.

    J'ai un peu de mal avec les Threads et je m'aperçoit que je ne fait pas correctement. Je vais corriger tout ca

    Par contre avec les TEvent j'ai pas tout saisit.

    Sinon concernant mon envoi de Signal, je met juste certaines sorties d'une carte Nationnal Instrument à 1 pour avoir un Front montant qui doit faire déclencher l'enregistrement d'un autre appareil, en aucun cas c'est bloquant.

Discussions similaires

  1. Gros problèmes d'affichage sur écran 16/9
    Par slylafone dans le forum C++Builder
    Réponses: 7
    Dernier message: 25/07/2006, 09h33
  2. Problème d'affichage d'un écrans
    Par tribaleur dans le forum Périphériques
    Réponses: 20
    Dernier message: 20/06/2006, 07h31
  3. Problème d'affichage sur un écran 16/9ème
    Par kurul1 dans le forum C++Builder
    Réponses: 2
    Dernier message: 23/01/2006, 11h51
  4. Problème d'affichage en plein écran
    Par kurul1 dans le forum C++Builder
    Réponses: 2
    Dernier message: 18/11/2005, 14h43
  5. Problème d'affichage d'une chaîne à l'écran
    Par Bubonik software dans le forum C
    Réponses: 7
    Dernier message: 08/05/2004, 20h47

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