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 :

Execution d'une action longue [Non suivi]


Sujet :

C++Builder

  1. #1
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut Execution d'une action longue
    Bonjour,
    J'ai un programme comprenant une boucle for classique. J'aimerais afficher l'état de la boucle dans une ProgressBar, et afficher cette progression en %.
    Lorsque j'execute cette action, ma ProgressBar évolue, mais l'affichage ne se fait pas. J'ai résolue ce problème en plaçant la ligne suivante:
    Application->MessageHandle();
    De ce fait, je rends la main durant la boucle pour que mon application gère les demandes. Le problème est que dans certains cas, j'éxécute une action d'affichage retardant considérablement ma boucle.

    Est-il possible de rendre la main à une seule commande?
    J'ai cherché la commande Application->ExecuteAction(*TBasic Action), mais je n'ai pas d'exemple, et l'aide ne me précise pas comment l'utiliser.

    Si quelqun sait comment faire pour rendre la main, juste le temps d'une ligne, je suis tout ouïe.
    Merci d'avance

  2. #2
    Membre chevronné
    Avatar de Gilles Louïse
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2002
    Messages : 421
    Points : 1 911
    Points
    1 911
    Par défaut
    On utilise aussi l'instruction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application->ProcessMessages();
    pour forcer les affichages et intercepter le clavier. Sinon, il faudrait savoir ce que fait cette boucle et nous montrer un peu de code pour qu'on puisse voir ce qui coince.

    À bientôt
    Gilles

  3. #3
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut
    Ma boucle est très longue, et elle fait principalement de l'extraction de chaines d'une AnsiString donnée par une ligne d'un TList. Une fois ces données décriptées, elles sont affichées dans un TChart.Je calcul un pourcentage de lignes traduites suivant le nombre total de ligne pour l'afficher. Le problème est que cet affichage se fait une fois la boucle terminée.

    Ma ProgressBar permet de rendre compte à l'utilisateur de l'avancement du chargement. Le soucis c'est qu'avec un Application->ProcessMessage, je vide la file d'attente des demandes en attente. L'affichage dans le TChart en même temps que le décryptage ralentit l'application, tandis que l'affichage d'une texte me disant "2.5%" ne le fais pas (du moins pas visiblement).

    Mais ce que je ne comprend pas c'est que je fais la même chose dans le cas de l'ouverture d'un fichier et qu'il me le charge sans l'afficher dans le TChart, mais en me mettant à jour le pourcentage. L'affichage se fait d'un seul coup une fois la boucle terminée, et la boucle est 10 à 15 fois plus rapide comme ça.

    C'est pourquoi j'aimerais garder cet avantage et n'afficher qu'une fois le traitement terminé. Donc que le processus traite les demandes du TChart à la fin et traite la demande de ma statusbar (affichage du pourcentage) dans ma boucle.

    Conclusion: j'aimerais donner la main à l'affichage de la statusbar, mais pas du chart durant cette période.

  4. #4
    Membre chevronné
    Avatar de Gilles Louïse
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2002
    Messages : 421
    Points : 1 911
    Points
    1 911
    Par défaut
    Je crois me souvenir que la position de l'instruction d'affichage compte, on ne peut pas trop la mettre n'importe où, elle doit se trouver à des niveaux faibles par rapport à la méthode (i.e. pas trop loin dans les imbrications de traitement) sinon vous avez ce genre de problème. En général on s'en sort en gérant un flag, ce qui permet de prendre la main à un niveau assez faible. Si ce n'est pas trop confidentiel, montrez-nous la structure de boucle et la position de l'instruction de mise à jour du ProgressBar. Sinon, essayez de comprendre mon idée et de structurer autrement votre boucle.

    À bientôt
    Gilles

  5. #5
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonjour, il existe également les possibilités suivantes
    1. emploi d'un thread sèécialisé pour le traitement des AnsiString
    2. dans la boucle appeller la Progress Bar par l'envoi d'un message pricé windows via la méthode PostMessage l'avantage de cette méthode est qu'elle n'est pas bloquante
    Cordialement

  6. #6
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut
    Ok, merci à vous tous pour vos suggestion, je vais essayer le PostMessage. En attendant, voici le code qui fonctionne :
    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
    for(ligne=0;ligne<Liste->Count;ligne++)
        {
            buffer=Liste->Strings[ligne];
            ListBox1->Items->Add(Liste->Strings[ligne]);
            while(i<buffer.Length())
            {
                while(buffer[i]!=';')
                {
                    c_buffer1[j-1]=buffer[i];
                    i++;
                    j++;
                }
                c_buffer1[j-1]='\0';
                buffer1=c_buffer1;
                X_charge=buffer1;
                j=1;
                i++;
                while(buffer[i]!=';')
                {
                    c_buffer1[j-1]=buffer[i];
                    i++;
                    j++;
                }
                c_buffer1[j-1]='\0';
                buffer1=c_buffer1;
                Val_charge=buffer1;
                j=1;
                i++;
                while(buffer[i]!=';')
                {
                    c_buffer1[j-1]=buffer[i];
                    i++;
                    j++;
                }
                c_buffer1[j-1]='\0';
                buffer1=c_buffer1;
                Date_charge=buffer1;
                j=1;
                i++;
                while(i<buffer.Length())
                {
                    c_buffer1[j-1]=buffer[i];
                    i++;
                    j++;
                }
                c_buffer1[j-1]='\0';
                buffer1=c_buffer1;
                Heure_charge=buffer1;
                j=1;
            }
            i=1;
            if(StrToInt(X_charge)> xmax)
            {
                xmax=StrToInt(X_charge);
                heure_fin=Heure_charge;
                Edit2->Text=IntToStr(xmax);
                Edit4->Text=heure_fin;
            }
            if(StrToInt(X_charge)< xmin)
            {
                xmin=StrToInt(X_charge);
                heure_debut=Heure_charge;
                Edit1->Text=IntToStr(xmin);
                Edit3->Text=heure_debut;
            }
            ProgressBar1->Position = StrToInt(X_charge);
            StatusBar1->Panels->Items[3]->Text=FloatToStrF((float)(ProgressBar1->Position)/(float)(ProgressBar1->Max)*100,ffFixed,3,1)+"%";
            Application->HandleMessage();
            Chart1->Series[0]->AddXY(StrToInt(X_charge),StrToFloat(Val_old_charge),Date_charge+" "+Heure_charge,clBlack);
            Chart1->Series[0]->AddXY(StrToInt(X_charge),StrToFloat(Val_charge),Date_charge+" "+Heure_charge,clBlack);
            if(X_charge!=table_mesure[mesure-1])
            {
                table_mesure[mesure]=StrToInt(X_charge);
                mesure++;
            }
            Val_old_charge=Val_charge;
        }
    //    nb_mesure=StrToInt(X_charge);
    /*
        Chart1->BottomAxis->Minimum=-1;
        Chart1->BottomAxis->Maximum=99999999999;
        Chart1->BottomAxis->Minimum=xmin;
        Chart1->BottomAxis->Maximum=xmax;
    */
      }
    et celui qui fonctionne, mais affiche dans le TChart:
    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
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    for(int i=0;i<Liste->Count;i++)
             {
                 buffer_ansi = Liste->Strings[i];
                 buffer_ansi = buffer_ansi.Trim();
    //extraction du temps
                 x=buffer_ansi.Pos(";");
                 temps = StrToInt(buffer_ansi.SubString(1,x-1));
                 buffer_ansi.Delete(1,x);
                 buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de la valeur
                 x=buffer_ansi.Pos(";");
                 val = StrToFloat(buffer_ansi.SubString(1,x-1));
                 buffer_ansi.Delete(1,x);
                 buffer_ansi = buffer_ansi.TrimLeft();
                 if(val == 0.5)
                    test++;
    //extraction de la date
                 x=buffer_ansi.Pos(";");
                 date = buffer_ansi.SubString(1,x-1);
                 buffer_ansi.Delete(1,x);
                 buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de l'heure
                 x=buffer_ansi.Pos(";");
                 heure = buffer_ansi.SubString(1,x-1);
                 buffer_ansi.Delete(1,x);
                 buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de l'écart
                 ecart = StrToInt(buffer_ansi);
                 if(i+1<Liste->Count)
                 {
                    buffer_ansi = Liste->Strings[i+1];
                    buffer_ansi = buffer_ansi.Trim();
    //extraction du temps
                    x=buffer_ansi.Pos(";");
    //                suiv_temps = StrToInt(buffer_ansi.SubString(1,x-1));
                    buffer_ansi.Delete(1,x);
                    buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de la valeur
                    x=buffer_ansi.Pos(";");
                    //suiv_val = StrToFloat(buffer_ansi.SubString(1,x-1));
                    buffer_ansi.Delete(1,x);
                    buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de la date
                    x=buffer_ansi.Pos(";");
                    suiv_date = buffer_ansi.SubString(1,x-1);
                    buffer_ansi.Delete(1,x);
                    buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de l'heure
                    x=buffer_ansi.Pos(";");
                    suiv_heure = buffer_ansi.SubString(1,x-1);
                    buffer_ansi.Delete(1,x);
                    buffer_ansi = buffer_ansi.TrimLeft();
    //extraction de l'écart
                    suiv_ecart = StrToInt(buffer_ansi);
                 }
                 if(val == 0.5 || prec_val == 0.5 || ecart!=0 && ( (ecart >= DEMI_BIT_MIN && ecart <= DEMI_BIT_MAX) || (ecart >= BIT_MIN && ecart <= BIT_MAX) ) && ( (suiv_ecart >= DEMI_BIT_MIN && suiv_ecart <= DEMI_BIT_MAX) || (suiv_ecart >= BIT_MIN && suiv_ecart <= BIT_MAX) ))
                 {
                    Chart1->Series[0]->AddXY(prec_temps,prec_val,prec_date+prec_heure,clBlack);
                    Chart1->Series[0]->AddXY(temps,prec_val,date+heure,clBlack);
                    Chart1->Series[0]->AddXY(temps,val,date+heure,clBlack);
                    bitok = true;
                    if(!DebutOK)
                    {
                        TempsDebut = temps;
                        DebutOK=true;
                    }
                    if(ecart >= DEMI_BIT_MIN && ecart <= DEMI_BIT_MAX)
                    {
                         if(demi_bit == false)
                         {
                             demi_bit = true;
                         }
                         else
                         {
                             trame = trame + "1";
                             demi_bit = false;
                         }
                    }
                    else
                    {
                        if(ecart >= BIT_MIN && ecart <= BIT_MAX)
                        {
                             trame = trame + "0";
                             demi_bit = false;
                        }
                        else
                        {
                             trame = "";
                        }
                    }
                 }
                 else
                 {
                    if(prec_val == 1 && bitok == true)
                    {
                        Chart1->Series[0]->AddXY(temps,1,date+heure,clBlack);
                    }
                    Chart1->Series[0]->AddXY(temps,0,date+" "+heure,clBlack);
                    bitok = false;
                    demi_bit = false;
                    DebutOK = false;
                    TempsFin = temps;
    //Traduction de la trame détectée
                    AnsiString buffer,buffer1,msg;
                    buffer = trame;
                    if(buffer.Length() >= 8)//si on a au moins un octet
                    {
                        int BitDelete=0;
                        BitDelete = buffer.Pos("1111110");
                        TabFrame[NumFrame][0]   = TempsDebut;
                        TabFrame[NumFrame++][1] = TempsFin;
                        if(BitDelete > 0 && BitDelete < buffer.Length()-7)
                        {//trame ayant un début
                            buffer.Delete(1,BitDelete+6);
                         //supression des bits supplémentaire X2D bit "0" après 5 bits à "1" à partir de l'octet de départ 7E
                            int SuppBit = 1;
                            buffer1 = "01111110";
                            while(SuppBit > 0 && buffer.Length() >5)
                            {
                                SuppBit=buffer.Pos("111110");
                                if(SuppBit > 0)
                                {
                                    buffer.Delete(SuppBit+5,1);
                                    buffer1 = buffer1 + buffer.SubString(1,SuppBit+4);
                                    buffer.Delete(1,SuppBit+4);
                                }
                            }
                            buffer.Insert(buffer1,1);
                            if(buffer.SubString(buffer.Length()-8,8) == "11111111")
                            {//trame complète
                                ListBox2->Items->Add(FrameDecod(1,buffer));
                            }
                            else
                            {//trame avec octet de début, mais avec octet de fin
                                ListBox2->Items->Add(FrameDecod(2,buffer));
                            }
                        }
                        else
                        {//trame sans octet de début
                            if(buffer.SubString(buffer.Length()-8,8) == "11111111")
                            {//trame sans octet de début, mais avec octet de fin
                                ListBox2->Items->Add(FrameDecod(3,buffer));
                            }
                            else
                            {//morceau de trame sans début ni fin
                                ListBox2->Items->Add(FrameDecod(4,buffer));
                            }
                        }
                        trame = "";
                    }
                 }
                 prec_temps = temps ;
                 prec_val   = val   ;
                 prec_date  = date  ;
                 prec_heure = heure ;
    //             prec_ecart = ecart ;
                 ProgressBar1->Position = temps;
                 StatusBar1->Panels->Items[3]->Text=FloatToStrF((float)(ProgressBar1->Position)/(float)(ProgressBar1->Max)*100,ffFixed,3,1)+"%";
                 Application->HandleMessage();
             }
    Si tu vois Gilles Louïse, quelque chose qui pourrait empécher cette affichage dans le TChart et ne pas géner celui dans la statusbar, je t'écoute mes oreilles grandes ouvertes.
    Merci encore pour vos suggestions

  7. #7
    Membre régulier
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Points : 115
    Points
    115
    Par défaut
    Bonjour,

    si tu veux, tu peux mettre du 'synchronize ()' dans ton thread.
    ca marche pas mal aussi.

  8. #8
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut
    Bonjour,
    Il est vrai que le Synchronize() serait la méthode adéquat. Seulement à la compilation, il m'indique qu'il ne connaît pas la fonction, et impossible de trouver dans quel .h il se trouve.
    Y a t il besoin d'une librairie particulière?

  9. #9
    Membre chevronné
    Avatar de Gilles Louïse
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2002
    Messages : 421
    Points : 1 911
    Points
    1 911
    Par défaut
    Votre programme est assez long, je me permets de vous dire que, sauf cas rarissime, on n'écrit pas de cette façon. Il faut subdiviser en sous-parties non seulement pour plus de clarté mais aussi pour plus de lisibilité. Il est rare qu'un sous-programme fasse plusieurs écrans. Trop de boucles imbriquées n'est jamais très bon.

    Cela empêche de vous aider plus sur le fond.

    À bientôt
    Gilles

  10. #10
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut
    Je sais, et je suis d'accord, mais pour le moment, je me concentre sur le résultat de mon application, ensuite je la découperais en plusieurs fonctions, permettant une clareté de lecture plus probante, plus tard. Cependant, je dois dire, pour ma défense , que les tabulations y sont pour beaucoup et qu'il se tient sur 2 pages à cause d'une seule ligne très importante.

  11. #11
    Membre éprouvé
    Avatar de bandit boy
    Profil pro
    Inscrit en
    Février 2006
    Messages
    916
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 916
    Points : 1 007
    Points
    1 007
    Par défaut
    Je n'arrive pas à faire que mon thread s'éxécute pendant ma boucle.
    Le Synchronize est considéré comme une fonction non définie, et le PostMessage n'a aucun effet.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if(PostThreadMessage(thread_id2,WM_USER,0,0) == -1)
    {
        ShowMessage("Erreur");
    }
    Peut être est ce que je n'utilise pas le bon message, mais je n'arrive pas à trouver les messages possibles et leurs effets.
    Si quelqun aurait une piste, je suis preneur.
    Merci d'avance

Discussions similaires

  1. ouvrir une popup et execution d'une action
    Par al3alwa dans le forum JSF
    Réponses: 1
    Dernier message: 01/09/2008, 11h41
  2. Problème lors de l'execution d'une action
    Par jshems dans le forum Struts 1
    Réponses: 4
    Dernier message: 21/07/2008, 15h13
  3. Probleme d'execution d'une action.
    Par lamnesie dans le forum JSF
    Réponses: 7
    Dernier message: 02/08/2007, 14h41
  4. Execution d'une action Struts par Ajax
    Par bonano dans le forum Struts 2
    Réponses: 18
    Dernier message: 04/06/2007, 16h19
  5. execution d'une requete longue
    Par nah_wah dans le forum SQL
    Réponses: 3
    Dernier message: 14/03/2007, 17h12

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