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 plantage de thread


Sujet :

C++Builder

  1. #1
    Membre éclairé Avatar de Baxter67
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 270
    Par défaut Probléme de plantage de thread
    Bonjours, j'avais il y a quelque temps fais un programma qui communique en TCP/IP avec un automate

    La partie de communication été mise dans un thread indépendant.

    Tous fonctionne parfaitement bien, sauf que quelque fois le thread "plante".

    Je m'explique : javais mis en place une sécurité, dans le thread de communication il y a une boucle infini, qui lit et écrie les donnée en permanence, et au début de cette boucle jai mis une incrémentation d'une valeur, si cette valeur ne change pas pendant 10 seconde de suite, je considére qu'il est coincé quelque part.
    C'est un Timer externe qui fais cette surveillance.


    Maintenant je voudrais savoir pourquoi il reste coincé, est ce possible que c'est du au fait que j'utilise des méthode de l'objet TCPClient sans utiliser Synchronize ?

    Quelqu'un voie pourquoi de temps en temps le thread peut rester coincé ??

    voila le code du thread en question :

    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
     
    void __fastcall TMonThread::Execute()
    {
      int i;
      int iCompteurRead=0;
      int iDebut, iNbr, iIndexRangement=0;
      int iDebutW, iNbrW;
      int iCompteurWrite=0;
      int iIndexRangementW=0;
      AnsiString asTmp;
      TDate d1,d2;
      TCoupleInt *ciCouple;
     
            //CODE DU THREAD DE LECTURE
            //on effectue dabord un sleep pour laiser a la com le temps de s'initialiser
            Sleep(100);
            //on effectue une boucle infinie pour effectuer le meme code a l'infini
            while(Form1->bFinThreadLec)
            {
                    Form1->clSurThread.isTCom++;
                    if(Form1->clSurThread.isTCom > 10000)
                            Form1->clSurThread.isTCom = 0;
     
                    d1=Now();   //recuperation de l'heure au debut de la sequence de requete
                    //boucle lisant les deux tableaux ou sont stocker les MW a lire (dans le premier) et le nombre de mw pour chaque requete (dans le deuxieme)
     
                    for(iCompteurRead=0;iCompteurRead<(Form1->ListMwRead->Count);iCompteurRead++)
                    {
                            if(Form1->iCompteurErreurCom < 2)
                            {
                                    ciCouple = (TCoupleInt *)(Form1->ListMwRead->Items[iCompteurRead]);
                                    iDebut = ciCouple->Valeur1;
                                    iNbr = ciCouple->Valeur2;
                                    if(LireMotsModbus(Form1->ListValeurLecture, iDebut, iNbr, iIndexRangement)==false)
                                            Form1->iCompteurErreurCom++;
                                    else
                                            Form1->iCompteurErreurCom = 0;
     
                                    iIndexRangement = iIndexRangement + StrToInt(ciCouple->Valeur2);
                            }
                    }
                    iIndexRangement=0;
                    iCompteurRead=0;
                    //boucle lisant les deux tableaux ou sont stocker les MW a écrire
                    //(dans le premier) et le nombre de mw pour chaqur requete (dans le deuxieme)
                    for(iCompteurWrite=0;iCompteurWrite<(Form1->ListMwWrite->Count);iCompteurWrite++)
                    {
                            if(Form1->iCompteurErreurCom < 2)
                            {
                                    ciCouple = (TCoupleInt *)(Form1->ListMwWrite->Items[iCompteurRead]);
                                    iDebutW = ciCouple->Valeur1;
                                    iNbrW = ciCouple->Valeur2;
                                    if(EcrireMotsModbus(Form1->ListValeurEcriture, iDebutW, iNbrW, iIndexRangementW)==false)
                                            Form1->iCompteurErreurCom++;
                                    else
                                            Form1->iCompteurErreurCom = 0;
     
                                    iIndexRangementW = iIndexRangementW + StrToInt(ciCouple->Valeur2);
                            }
                    }
                    iIndexRangementW=0;
                    iCompteurWrite=0;
                    d2=Now();  //recuperation de l'heure a la fin de la sequence de requete
                    //calcul du temps en ms qu'a mis le programme pour faire toute les requetes
                    Form1->iTempsCom=StrToInt(FormatDateTime("szzz",d2-d1));
                    Form1->TimerSurveilance->Enabled = true;
            }
     
            Form1->bTLecFini = true;
    }

    Cordialement Baxter

  2. #2
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Par défaut
    Salut,

    J'ai déjà eu ce genre de "blocage", et en déportant tout le code liée à mes "TForm" dans un "syncrhonize()", plus de blocage... par contre, les "blocages" terminaient direct la thread...

    ou alors, faut passer par une structure (classe?) qu'on partage entre la thread et la form, mais alors, faut protéger par mutex ou autre...

    Bon courage!

  3. #3
    Membre éclairé Avatar de Baxter67
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 270
    Par défaut
    Bon je vais toute la partie lire et ecrire par thread voir ce ke sa donne
    mais je fais un sleep dans chaque cas, et si il le fais dans le synchronize sa risque detre genant pour moi je c pas trop :S

  4. #4
    Membre éclairé Avatar de Baxter67
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 270
    Par défaut
    Bon maintenant j'ai un probléme pour tous faire avec un synchronize

    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
     
    //---------------------------------------------------------------------------
    //Fonction Ecriture Mot
    bool EcrireMotsModbus(TList *ListTab, int iPremier, int iNbr, int iIndex)
    {
      unsigned char *BufferEnvoie;
      unsigned char BufferW[20];
      unsigned char usTmp = (unsigned char)iNbr;
      unsigned char usTmp2 = (unsigned char)(iNbr*2);
      int iCpt=0;
      TCoupleInt *ciValTmp;
     
            /*BufferEnvoie est le buffer ou est créé la trame a envoyer a l'automate
            BufferW est le buufer ou est stocké la reponde de l'automate
            usTmp et usTmp2 sont deux unsigned char ou sont stocké les valeur de iNbr et iNbr*2
            j sert de compteur de sécurité pour ne pas faire une attente infini et iCpt de compteur pour stocker les valeur*/
     
            //création dynamique du tableau de requete en fonction du nombre de trame a lire
            BufferEnvoie = new unsigned char [(iNbr*2)+13];
            BufferEnvoie[0]=(unsigned char)00;
            BufferEnvoie[1]=(unsigned char)00;
            BufferEnvoie[2]=(unsigned char)00;
            BufferEnvoie[3]=(unsigned char)00;
            BufferEnvoie[4]=(unsigned char)00;
            //Ce champ contien le nombre de champs ki suive
            BufferEnvoie[5]=(unsigned char)2*iNbr+7;
            BufferEnvoie[6]=(unsigned char)00;
            //code requete 16 en decimal ou \x10 en héxa pour une ecriture de plusieur mots
            BufferEnvoie[7]=(unsigned char)16;
            //Premier mot a envoyer codé sur 2 bit
            BufferEnvoie[8]=SeparateFort(iPremier);
            BufferEnvoie[9]=SeparateFaible(iPremier);
            //Nombre de mot a ecrire
            BufferEnvoie[10]=(unsigned char)00;
            BufferEnvoie[11]=usTmp;
            //Nombre de mot a ecrire *2
            BufferEnvoie[12]=usTmp2;
     
            //boucle ki stocke les valeur a ecrire en fonction de l'index.
            //Chaque mot est stocké sur 2 bit a partir de la case 13
            // premier case 13 et 14    deuxieme case  15 et 16 et ainsi de suite
            for(int i=13; i<((iNbr*2)+13);i=i+2)
            {
                    ciValTmp = (TCoupleInt *)(ListTab->Items[iCpt+iIndex]);
                    BufferEnvoie[i]=SeparateFort(ciValTmp->Valeur2);
                    BufferEnvoie[i+1]=SeparateFaible(ciValTmp->Valeur2);
                    iCpt++;
            }
     
            //Envoie de la requete d'ecriture
     
            //remise a zero de la case 7 et 8 pour etre sur qu'on effectue bien l'attente
            BufferW[7]=0;
            BufferW[8]=0;
            Form1->OpenModBusClient->SendBuf(BufferEnvoie,(iNbr*2)+13);
            //Attente de la reponse de l'automate
            Sleep(Form1->iSleepCom);
            Form1->OpenModBusClient->ReceiveBuf(BufferW,20);
     
            if(BufferW[7]!=16)
            {
                    return false;
            }
     
            delete [] BufferEnvoie;
            return true;
    }
    //---------------------------------------------------------------------------

    ceci est la fonction ecrire mot, elle est appelé dans le thread
    je voulais appelé cette fonction avec un synchronize mais je me suis rendu compte que javais mis un sleep dans la fonction.
    Si je l'appelle avec un synchronize le sleep va bloquer l'application principale.

    Quelqu'un a une idée pour remplacer le sleep par quelque chose de non bloquant?

    Et derniere question peut on passé des paramétre a une fonction appelé avec synchronize et retourné quelque chose?

    Cordialement Baxter

  5. #5
    Membre éclairé Avatar de Baxter67
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 270
    Par défaut
    Bon jai trouvé un code ASM en delphi pour faire un sleep non bloquant

    Quelqu'un saurais coment le convertir en C++ ?

    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
     
    procedure Pause(t: DWORD); register;
    asm
      push ecx
      push ebx
      mov ecx, eax
      call GetTickCount
      mov ebx, eax
    @attente:
      push ebx
      push ecx
      mov eax, Application
      call [EAX].TApplication.ProcessMessages
      push 1
      call Sleep
      pop ecx
      pop ebx
      call GetTickCount
      sub eax, ebx
      cmp eax, ecx
      jnae @attente
      pop ebx
      pop ecx
    end;
    Cordialement Baxter

  6. #6
    Membre éclairé Avatar de Baxter67
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 270
    Par défaut
    Bon j'ai trouvé un code pour faire un sleep non bloquant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void Sleep2(int iTemps)
    {
      TDate dTimeDebut;
      int iMsBetween = 0;
     
            dTimeDebut = Now();
            while(iMsBetween <= iTemps)
            {
                    Application->ProcessMessages();
                    iMsBetween = MilliSecondsBetween(dTimeDebut, Now());
            }
    }

    Maintenant ma seul question reste :

    Comment passé des argument a une fonction appelé par un Synchronize ??

Discussions similaires

  1. Réponses: 7
    Dernier message: 18/09/2006, 22h01
  2. [C#] problème : ou placer un thread???
    Par othland dans le forum Windows Forms
    Réponses: 1
    Dernier message: 07/04/2006, 19h46
  3. Problème de communications entre threads
    Par maya09 dans le forum Windows
    Réponses: 1
    Dernier message: 22/02/2006, 22h18
  4. Problème de création de thread
    Par [Silk] dans le forum Langage
    Réponses: 2
    Dernier message: 31/01/2006, 21h58
  5. Problème de creation de thread sous linux
    Par xilebo dans le forum POSIX
    Réponses: 4
    Dernier message: 27/10/2004, 09h58

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