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++ Discussion :

exécuter une fonction tout les xx secondes


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut exécuter une fonction tout les xx secondes
    bonjour,

    je souhaite faire une fonction qui exécute une tache toutes les xx secondes. L'utilisateur entre un temps en secondes, je récupère cette valeur et ensuite je lance la fonction qui exécute une tache spécifique toutes les xx secondes.

    Exemple simple : si l'utilisateur spécifie 30 secondes, afficher "Bonjour" toutes les 30 secondes.

    Pouvez-vous me donner des pistes de recherche svp ?

    Merci de votre aide.

  2. #2
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Et bien tu utilises time. Une boucle while() et hop!
    Homer J. Simpson


  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    bonjour,

    merci de votre reponse.
    Je suis assez novice en c++. Comment puis-je avec un while reconstruire un chronomètre ? ce que je veux est de déclencher l'action toutes les 30 secondes par exemple.

    Time me renvoie la date actuelle.

    Pouvez-vous me donner un peu plus de détails svp ?

    Merci d'avance.

  4. #4
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Et bien tu utilises time. Une boucle while() et hop!
    Ça sous entend une attente active, c'est pas super

    Ça peut se faire très facilement avec sleep_for.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    bonjour,

    J'ai finalement trouve la solution pour exécuter ma tache toutes les xx secondes. Malheureusement ce n'est pas vraiment une solution élégante. Je fais une boucle while() mais je en sors jamais de cette boucle (boucle infinie) et en plus de cela je perds la main sur mon interface graphique ...

    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
     
           time_t t1, t2;
     
            t1 = time(NULL);
     
            while(1)        //probleme de boucle infinie
           {
                t2 = time(NULL);
     
                if(difftime(t2, t1) == 30) // exemple pour 30 secondes
                {
                   t1 = t2;
                   std::cout<<"execution de la tache"<<std::endl;
                }
            }

  6. #6
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par med.doc Voir le message
    J'ai finalement trouve la solution pour exécuter ma tache toutes les xx secondes. Malheureusement ce n'est pas vraiment une solution élégante. Je fais une boucle while() mais je en sors jamais de cette boucle (boucle infinie) et en plus de cela je perds la main sur mon interface graphique ...
    Dans ce cas exécute ta boucle dans un nouveau thread.

  7. #7
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Voici quelques pistes.

    D'une part il te faut exécuter ta boucle dans un autre thread, et d'autre part cette solution avec une boucle infinie n'est franchement pas top : ta boucle va te bouffer un CPU à 100%.

    Tu ferais mieux d'utiliser des fonctionnalités C++11 qui vont bien comme ceci et ceci.

    Un choix simple est de faire un sleep toutes les secondes et de checker la valeur du temps écoulé à ce moment là. Il te faut aussi penser à un mécanisme pour mettre fin à la boucle et tuer le thread quand tu finis ton programme. Un std::atomic_bool à affecter au moment de l'arrêter est un bon choix ici.

    Je peux te donner plus de précisions si tu n'avances pas avec ça.
    Find me on github

  8. #8
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    bonjour,

    je vous remercie de votre reponse.
    j'ai bien peur que cela me dépasse un peu, j'ai compris d’après la page que je dois lancer un sorte de programme indépendant de mon programme courant.
    comment je peux adapter cela a l'exemple de ma boucle while() ?

    Pouvez-vous me donner un coup de main au niveau de la syntaxe ?

    merci de votre aide

  9. #9
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par med.doc Voir le message
    Pouvez-vous me donner un coup de main au niveau de la syntaxe ?
    Tu peux, au choix, en fonction de la taille réelle de la boucle :
    * utiliser une lambda (mais ici, la boucle semble un peu grosse pour que le code reste compréhensible facilement)
    * utiliser une fonction (membre ou libre, std::bind (ou une lambda) de permettra de faire marcher ça.
    * utiliser un foncteur (utile si le bout de code doit être réutillisable)

    Niveau syntaxe
    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
    // lambda
    std::thread t([]() {
       // ta boucle
    });
     
    // fonction membre
    std::thread t(std::bind(&UneClasse::fonctionQuiContientLaBoucle, uneInstanceDeUneClasse));
    // ou 
    std::thread t([&uneInstanceDeUneClasse]() {
       uneInstanceDeUneClasse.fonctionQuiContientLaBoucle();
    });
     
    // fonction libre
    std::thread t(&fonctionQuiContientLaBoucle);
     
    // foncteur
    struct Foncteur {
        void operator()() {
            // ta boucle
        }
    };
    std::thread t(Foncteur());
     
    // pour toutes les solutions
    // à la fin du programme, ou quand le thread n'est plus utile :
    t.join();
    Utilise plutôt sleep_for pour l'attente, ça fera une attente passive : ça n'utilisera pas inutilement le CPU.

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    bonjour,

    merci beaucoup pour votre réponse.

    j'essaye d’écrire une fonction en suivant vos exemples de syntaxe, mais lorsque je compile,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::this_thread::sleep_for
    n'est pas reconnu. Pourtant j'ai bien inclue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include "chrono"
    #include "thread"
    .... en cherchant sur le net, je vois que n'est disponible que pour c++11. Je développe en c++ sous Qt, mais je ne sais pas comment garantir cette compatibilité avec c++11.

    Merci encore une fois pour votre aide.

  11. #11
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Ça sous entend une attente active, c'est pas super
    Comment ça une attente active? Un thread n'est pas obligatoire, une boucle while(1) ok mais il faut gérer la condition de break.
    C'est simple, a chaque boucle tu incrémentes un dt qui est la durée de la dernière boucle, tu les additionnes a chaque boucle, si ton dt est supérieur ou égal a X milliseconde, tu appelles ta fonction. Si tu veux en même temps pouvoir faire un input etc.. évidemment un thread serait mieux mais compliqué je pense pour ce que tu veux faire.
    Homer J. Simpson


  12. #12
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Tu vas devoir aborder beaucoup de nouvelles notions. Si tu veux coder avec une GUI, tu dois apprendre et comprendre ce qu'est un thread. Tu dois aussi apprendre ce que sont les références en C++.

    Pour t'aider, je te donne un bout de C++11 qui fait un peu ce que tu demandes. C+11 est la nouvelle norme du C++ et il est probable que tu doives configurer la compilation pour le prendre en charge. Je te le donne pas que tu le copies-colles mais pour que tu comprennes ce que ça fait. Le programme affiche "Coucou !" toutes les 100 millisecondes.

    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
    #include <iostream>
    #include <chrono>
    #include <thread>
    #include <ctime>
    #include <atomic>
     
    void called() {
        std::cout << "Coucou !" << std::endl;
    }
     
    struct caller {
        std::atomic_bool& stop;
     
        caller(std::atomic_bool& stop_) : stop(stop_) {}
        caller(caller const& other) : stop(other.stop) {}
        caller( caller&& other ) : stop(other.stop) {}
     
        void operator() () {
            auto t_start = std::chrono::high_resolution_clock::now();
            std::chrono::milliseconds delay(100);
            while(!stop) {
              std::this_thread::sleep_for(std::chrono::milliseconds(10));
              auto t_now = std::chrono::high_resolution_clock::now();
              std::chrono::milliseconds elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(t_now - t_start);
              if(delay <= elapsed) {
                  t_start = t_now;
                  called();
              }
            }
        }
    };
     
    int main()
    {
        std::atomic_bool stop(false);
        caller c1(stop);
        std::thread thread1(c1);
     
        // Launch your gui, I put a sleep just to show how it tworks
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
     
        // Stop it
        stop = true;
        thread1.join();
     
        return 0;
    }
    Ici je lance un thread avec un boucle while qui est exécutée toutes les 10 millisecondes. Si j'ai atteint mon délai (100 millisecondes), je fais l'action demandée (afficher "Coucou") et je recommence à attendre.

    L'usage de stop permet d'arrêter le thread lorsque tu le désires. Le fait qu'il s'agisse un atomic_bool sert à le protéger car il est utilisé par plusieurs threads (le principal, et celui qu'on a lancé).
    Find me on github

  13. #13
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    merci beaucoup pour vos réponses.

    Cette notion est effectivement nouvelle pour moi.
    Je vais me plonger dedans et essayer de comprendre, puis je reviendrai vers vous.

    merci encore une fois pour votre aide

  14. #14
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    @jblecanard, On peut passer le delai en paramètre du foncteur, le foncteur se résume à
    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
    struct caller {
    std::atomic_bool& stop;
    std::chrono::milliseconds delai;
     
    caller(std::atomic_bool& stop_, const std::chrono::milliseconds& delai) : stop(stop_) , delai(delai) {}
    caller(caller const& other) : stop(other.stop), delai(other.delay) {}
    caller( caller&& other ) : stop(other.stop), delai(other.delai) {}
     
    void operator() () {
        while(!stop) {
          std::this_thread::sleep_for(delai);
          called();
        }
    }
    };

  15. #15
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    @med.doc : Tu n'es pas obligé d'utiliser C++11, Qt contient aussi tout ce qu'il faut pour faire des threads et des timers.

    Citation Envoyé par Iradrille Voir le message
    @jblecanard, On peut passer le delai en paramètre du foncteur, le foncteur se résume
    En effet, mais j'ai pas trop poussé l'abstraction car je pense que med.doc va un peu ramer. Tu peux aussi stocker la fonction à appeler dans un callable et la passer également en paramètre.

    D'autre part, l'intérêt de ne pas faire un sleep du délai complet permet d'arrêter le thread plus vite. Par exemple, avec ton foncteur, en fin de programme, si le délai est de 30 secondes et que ton thread vient de commencer une attente, tu vas être obligé d'attendre 30 secondes pour que le thread s'arrête. Avec ma solution tu peux réduire ce temps à moins (le délai intermédiaire).

    Pour pousser le vice au maximum, faudrait utiliser libevent mais on sort du cadre du post là.

    Citation Envoyé par Astraya Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Ça sous entend une attente active, c'est pas super
    Comment ça une attente active? Un thread n'est pas obligatoire, une boucle while(1) ok mais il faut gérer la condition de break.
    Un while(1) sans sleep dedans est une attente active consommatrice de CPU, que ce soit dans un autre thread ou pas n'y change rien.
    Find me on github

  16. #16
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    la solution d'Astraya est correcte, mais à envisager dans un cas plus concret et grand.

    Si la question est juste "je veux lancer ça, attendre X s et lancer ça", alors un sleep fait l'affaire.
    Si la question est plutôt "j'ai une appli qui tourne et doit effectuer telle action toutes les X s", alors la solution d'Astraya est préférable. Mais il convient de la mettre en place correctement...

    Dans ton appli, tu auras un Update appelé à chaque frame, dans cette Update tu auras un timer qui évolue du DT à chaque appel, quand le DT a passé le timer voulu, tu appel ta fonction.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void Update(dt)
    {
     my_time += dt;
     if (my_time >= "sleeping time")
     {
        Action();
        my_time = 0;
     }
    }
    Btw, c'est le cas d'utilisation typique dans le jeu-vidéo ou beaucoup de système de simulation . Ca permet de faire évoluer tous les acteurs de ton appli d'un même timer.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  17. #17
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    bonjour a tous,

    Je vous remercie beaucoup pour toute votre aide, mais malheureusement je suis un peu dépassé par toutes ces notions, et j'ai besoin de bien du temps pour comprendre. Pensez-vous qu'il est plus simple, même si pas très élégant, d'utiliser une boucle while() (ma boucle infinie) mais avec un sleep() dedans, afin que le processus ne tourne pas en continu ?

    c'est a dire que lors de l'attente des 30 secondes, est-ce que le sleep me permet de retrouver la main sur mon programme, ensuite la tache s’exécute (je pers la main le temps de l’exécution du programme (quelques millisecondes) .... ainsi de suite.

    qu'en pensez-vous ? est-ce faisable ?

    Merci encore pour votre soutient

  18. #18
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par med.doc Voir le message
    c'est a dire que lors de l'attente des 30 secondes, est-ce que le sleep me permet de retrouver la main sur mon programme, ensuite la tache s’exécute (je pers la main le temps de l’exécution du programme (quelques millisecondes) .... ainsi de suite.
    Ta as 2 threads qui tournent, l'un s'occupera de la GUI, l'autre exécutera la tache de tu lui donne, tout les 30 secondes. le 1er thread continue son execution après la création du thread, le thread créé commence sa vie dans la fonction que tu passes au thread.
    Tu ne perd jamais la main, les 2 threads s'exécutent en parallèle.

    @bousk, Quel est l'intérêt exact de l'attente active ? J'ai du mal à voir ce qu'elle apporte par rapport à une attente passive.

    edit: Je viens de comprendre. Effectivement ça peut être utile. Et une bonne solution avec un seul thread.

  19. #19
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Janvier 2013
    Messages
    51
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 51
    Points : 34
    Points
    34
    Par défaut
    bonjour Iradrille,

    ma question était plutôt de savoir si je peux faire cela sans passer par les threads ?

    merci

  20. #20
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    ma question était plutôt de savoir si je peux faire cela sans passer par les threads ?
    Oui bien entendu. Avant la technique du while et du time de chaque frame comme tu as fait pour ta première solution. Si tu veux limiter le nombre de frame ( boucle par seconde ) rajoute un sleep en fonction de ton diff_time. Ça peux te permettre de limiter les FPS à un nombre de frame maximum et de le rendre passif

    Par exemple, tu peux faire 60 FPS, soit 16.66 millisecond par frame tu doit faire un sleep de 16.66 - diff_time si ton diff time est plus petit que 16.66 ( cela veut dire que ta frame est trop rapide et que tu veux qu'elle attende pour reboucler )
    Homer J. Simpson


+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Exécuter une fonction toutes les 2 minutes en VB.NET
    Par sihammaster dans le forum VB.NET
    Réponses: 3
    Dernier message: 14/10/2012, 00h29
  2. Exécuter une fonction toutes les X minutes ?
    Par corgato dans le forum Qt
    Réponses: 8
    Dernier message: 27/01/2009, 10h29
  3. Exécuter une macro toutes les 3 secondes
    Par lucazzo dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 25/06/2008, 09h42
  4. Exécuter une fonction toutes les 2ms
    Par ditchou dans le forum Langage
    Réponses: 3
    Dernier message: 08/02/2008, 17h54
  5. Réponses: 7
    Dernier message: 13/01/2008, 16h52

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