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 de Thread


Sujet :

C++Builder

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut Problème de Thread
    Bonjour,

    J'ai un petit soucis avec les Thread!!!

    Au démarrage de mon interface graphique, j'ai un premier Thread qui se lance automatiquement (ça me parait logique).
    Quand j'appuie sur un bouton, je crée un nouveau Thread qui sert pour envoyer un fichier.
    Le fichier transmis, le thread se détruit comme prévus, mais je peux pas envoyer un second fichier si j'appuie de nouveau sur le bouton.

    J'ai regardé en mode debogage et je vois que le premier thread est dans le status Inconnu et état Arrêté quand je crée l'autre Thread.

    Est ce que cela signifie que je n'ai plus accès au 1er Thread, enfin que mon programme ne retrouve pas le Thread qui a été créé automatiquement??

    Si tel est le cas, comment je peux faire pour palier se problème?? Dois je rajouter un truc dans le OnTerminate du Thread que je crée pour rebasculer sur le Thread principal??

    Sinon si quelqu'un à une idée de ou cela peut venir??


    Je vous remercie par avance...

    fmr

  2. #2
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Points : 578
    Points
    578
    Par défaut
    Hello
    Citation Envoyé par fmr130 Voir le message
    Le fichier transmis, le thread se détruit comme prévus, mais je peux pas envoyer un second fichier si j'appuie de nouveau sur le bouton.

    J'ai regardé en mode debogage et je vois que le premier thread est dans le status Inconnu et état Arrêté quand je crée l'autre Thread.

    Est ce que cela signifie que je n'ai plus accès au 1er Thread, enfin que mon programme ne retrouve pas le Thread qui a été créé automatiquement?
    Si le 1er thread est détruit, ça paraît normal que tu n'y aies plus accès.
    Est-ce que tu peux poster un peu de code (création du thread...) ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut
    Salut et merci d'avoir répondu,

    Je suis arrivé à le faire marcher correctement, mais j'ai toujours un petit problème qui est le suivant :
    Pour dire que je veux que mon Thread se termine de force je fais ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
          envoyer(stop,2,0);
          MonThread -> Terminate();
          MainForm -> Edt_Details -> Text = "Transfert terminé";
    Donc la valeur Terminated devient égal à true. Certaine fois il ne prend pas en compte cette commande : MonThread -> Terminate(); car le Thread reste actif.

    Y a t'il un moyen de vérifier l'état de Terminated??? pour etre sur que la commande a bien été pris en compte.
    Ou une méthode pour vérifier si le Thread à bien été détruit??

  4. #4
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Salut fmr130
    Comportement apparamment normal
    Tire de l'aide en ligne
    Signale au thread de s'arrêter en affectant la valeur true à la propriété Terminated.
    void __fastcall Terminate(void);
    Description
    Terminate affecte la valeur true à la propriété Terminated du thread, en signalant que le thread doit se terminer dès que possible.
    Pour que Terminate fonctionne, la méthode Execute du thread et toute méthode appelée par Execute doit tester périodiquement Terminated et quitter lorsqu'elle vaut true.
    --
    Plutot que d'essayer de réinventer la roue, apprenons à nous en servir

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut
    Oui ça je le fais bien dans mon Thread.
    Voila le code complé de mon 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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    void __fastcall TMonThread::Execute()
    {
       /* Ouvrir le Port USB                                                 */
       /* ------------------------------------------------------------------ */
       while(i != 1)
       {
          i = OpenPort();
       }
       /* MAJ des données suivantes                                          */
       /* ------------------------------------------------------------------ */
       i=0;
       flux_control = XON;              /* Force le XON au départ         */
     
       /* Ouvrir le fichier sélectionné et tester son existance              */
       /* ------------------------------------------------------------------ */
       f = fopen(nom,"rb");
       if (f == NULL)                     /* Si nul retourné faux donc       */
          ErrorForm->Display();           /* Afficher erreur                 */
     
       else                               /* Sinon                           */
       {
          Synchronize(AffMessage);
     
          /* Envoie de la commande Start                                     */
          /* --------------------------------------------------------------- */
          if (enregistrer == 0)           /* Si pas enregistrer ds dataflash */
             envoyer(start, 4, bytesWritten);
          else                            /* Sinon envoyer com enregistrer   */
          {
             envoyer(record, 1, bytesWritten);
          }
     
          /* Envoie du fichier                                               */
          /* --------------------------------------------------------------- */
     
          while(1)                         /* Tant que fichier pas fini      */
          {
             char Buf[800]={0};            /* Initialisation du buffer       */
             if (flux_control == XON)      /* Si transmission permise        */
             {
                bytesRead = fread(Buf,1,14,f);/* Récupère 14 car.            */
     
                if ((bytesRead == 0 )|| (Terminated == true))        /* Si plus de car. ds fichier     */
                {
                   fclose(f);              /* Fermer le fichier ouvert       */
                   break;                  /* Fin du Thread                  */
                }
                else                       /* Sinon                          */
                {
                   s = Buf;                /* Mettre les valeurs du buf ds s */
                   bytesWritten = 0;       /* Initialisation de BytesWritten */
     
                   /* Envoyer les caractères                                 */
                   /* ------------------------------------------------------ */
                   envoyer(s, bytesRead, bytesWritten);
                   s += bytesWritten;      /* Incrémenter s du Nbre de car   */
                   bytesRead -= bytesWritten; /* Décrémenter bytes lus       */
     
                   /* Redonne la main au graphique                           */
                   /* ------------------------------------------------------ */
                   Sleep(10);              /* Mettre en veille 10 ms         */
                }
             }
             Sleep(50);                    /* Tempo de 50 ms                 */
     
             /* Gestion du contrôle du flux                                  */
             /* ------------------------------------------------------------ */
             car = recevoir();   /* Récupèrer car. reçu            */
             if (car == 19)                /* Si car = XOFF                  */
             {
                i=2;                       /* Pour selectionné le message    */
                Synchronize(AffMessage);   /* Afficher le message            */
                flux_control = XOFF;       /* Signale transmision pas permis */
             }
             else if (car == 17)           /* Si car = XOFF                  */
             {
                i = 3;                     /* Pour selectionné le message    */
                Synchronize(AffMessage);   /* Afficher le message            */
                flux_control = XON;        /* Signale transmision permise    */
             }
          }
          //if (bytesRead == 0 )
          {
             envoyer(fin, 1, 0);    /* Envoie car. de fin de fichier  */
             i=4;                             /* Pour selectionné le message    */
             Synchronize(AffMessage);         /* Afficher le message            */
          }
       }
       ClosePort();              /* Fermer le Port USB             */
       /* Autoriser l'acces aux boutons suivants                             */
       /*------------------------------------------------------------------- */
       EnableWindow(MainForm -> Btn_Commencer       -> Handle, TRUE);
       EnableWindow(MainForm -> Btn_Enregistrer     -> Handle, TRUE);
       EnableWindow(MainForm -> Btn_Valider_        -> Handle, TRUE);
       EnableWindow(MainForm -> Btn_Ouvrir          -> Handle, TRUE);
       EnableWindow(MainForm -> Box_Read_Data_flash -> Handle, TRUE);
       EnableWindow(MainForm -> Box_Save_Data_flash -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_Classe_veh_     -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_Duree_Test_     -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_Vitesse_        -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_InterDistance_  -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_Nbre_vehicules_ -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_Amplitude_      -> Handle, TRUE);
       EnableWindow(MainForm -> Edt_Duree_          -> Handle, TRUE);
     
    }

    je le test dans mon while (1) avec if ((bytesRead == 0 )|| (Terminated == true))

    Mais ça peut marcher 15 fois desuite et la 16eme fois déconné...

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut
    Bon j'ai pas trouvé l'erreur mais je sais ce qui provoque ce dysfonctionnement.
    Il s'agit de ma fonction pause qui est la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
          if (MainForm -> Btn_Pause -> Tag == 0)/* Si pause n'est pas activé */
          {
             MonThread -> Suspend();
             envoyer(pause,2,0);                /* Mettre en pause           */
             MainForm -> Btn_Pause -> Tag = 1;  /* Pause est activé          */
             EnableWindow(MainForm -> Btn_Arret     -> Handle, FALSE);
          }
          else                                  /* Sinon pause est activé    */
          {
             envoyer(reprise,2,0);                /* reprendre           */
             MonThread -> Resume();
             MainForm -> Btn_Pause -> Tag = 0;  /* Pause n'est plus activé   */
             EnableWindow(MainForm -> Btn_Arret     -> Handle, TRUE);
          }
    Ce qui est bizarre, c'est que si je fais juste une fois pause (puis reprise) et que je demande d'arrêter le transfert de données, le Thread est bien détruit.
    Mais si je met 2 fois en pause (puis reprise) et que je demande d'arrêter le transfert de données, le Thread ne se détruit plus.

    Quelqu'un voit un truc??? car moi la je vois pas trop!!!

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut
    Bon si j'enleve la pause et la reprise du thread cela fonctionne très bien.

    Mais je comprend vraiment pas pourquoi!!!

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Points : 446
    Points
    446
    Par défaut
    D'après la doc, il faut appeler "Resume()" autant de fois qu'il y a eu des "Suspend()".

    Est-il possible que ton thread principal appelle X milliers de fois le "Suspend()" si ton test est dans une boucle (puisque que "if (MainForm -> Btn_Pause -> Tag == 0)" est toujours évalué comme vrai) mais que le "Resume()" n'est appelé qu'une seule fois?

    Dans ces conditions, ton thread ne repartirait jamais après avoir été mis en pause...

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut
    Je sais pas trop quoi te répondre lol.

    Non sérieusement je pense pas car l'événement pause se fait que quand j'appuie sur le bouton pause, donc pas dans une boucle. De même quand je appuie de nouveau sur le même bouton pause alors il fait reprendre le transfert de fichier.

    La ça marche grâce à mon contrôle de flux XON/XOFF, c'est à dire que pendant la pause, le thread tourne toujours, mais ne fais rien du tout car il reçoit un XOFF (tôt ou tard) et attend de recevoir un XON pour envoyer d'autres données. Donc un peu inutile de le faire tjs tourner et surtout pas beau!!!

  10. #10
    Membre averti

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    351
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2005
    Messages : 351
    Points : 446
    Points
    446
    Par défaut
    Alors tu as un double contrôle sur ton thread:
    1) Via le XON/XOFF
    2) Via le suspend/resume

    Peut-être y a-t-il conflit entre ces deux modes.

    Es-tu sûr que ton caractère XON a bien été reçu après la seconde pause? Peut-être est-il bloqué en XOFF parce que ta séquence est:
    1) Tu suspends le thread (suspend())
    2) Tu envoies un XOFF (il n'est donc pas reçu par le thread qui est suspendu)
    3) time passes
    4) Tu envoie un XON (qui n'est toujours pas reçu par le thread)
    5) Tu réactives le thread (resume())

    Peut-être faudrait-il n'utiliser qu'un système (soit XON/XOFF soit suspend/resume) ou changer l'ordre:
    1) Envoyer XOFF: le thread ne travaille plus
    2) Le suspendre
    3) time passes
    4) Reprendre le thread
    5) Envoyer XON

    Qui imbrique les méthodes d'arrêt correctement

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    50
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 50
    Points : 38
    Points
    38
    Par défaut
    Vraiment pas bête du tout je vais essayer mais je suis sur que tu as raison car dans mon Thread je demande de vérifier si je ne reçois rien (donc le XON/XOFF).

    Je vais suivre ta piste (ou plutôt ton autoroute lol).

    Merci encore à tous le monde de m'avoir aider.

    fmr

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de thread : Plus de ressources système
    Par OliverSleep dans le forum C++Builder
    Réponses: 17
    Dernier message: 07/02/2006, 15h35
  2. [VB.NET] Problème de Thread
    Par Sadneth dans le forum ASP.NET
    Réponses: 26
    Dernier message: 31/01/2006, 10h12
  3. Problème synchronisation threads
    Par Linio dans le forum Concurrence et multi-thread
    Réponses: 19
    Dernier message: 11/01/2006, 16h57
  4. [MFC] Problème de Threads + Timers
    Par Invité dans le forum MFC
    Réponses: 8
    Dernier message: 30/11/2005, 10h51
  5. [VC++6][DX9] Problème de thread lors d'un blit ...
    Par grandjouff dans le forum DirectX
    Réponses: 2
    Dernier message: 12/06/2003, 22h22

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