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

Threads & Processus C++ Discussion :

Utilisation de CreateThread c++


Sujet :

Threads & Processus C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 18
    Par défaut Utilisation de CreateThread c++
    Bonjour,

    Je souhaite créer un Thread avec CreateThread().
    Ce thread a pour but d'envoyer des messages toutes les N secondes (avec N qui varie de 2 à 15).

    J'ai créé le thread de cette manière:
    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
     
    c_treatment::c_treatment()
    {
      thread_ok = true;
      DWORD dwThreadId = 0;
      HANDLE th = CreateThread(NULL, 0, myThread, (LPVOID)this, 0, &dwThreadId);
    }
     
    DWORD WINAPI myThread(LPVOID arg)
    {
      c_treatment *tr = (c_treatment *)arg;
      while (tr->thread_ok) 
      {
         tr->updateMessage();
      }
      return 0;
    }
    Le thread est actif pendant 30 minutes à peu près (le paramètre thread_ok vaut "true" au début, puis "false" au bout de 30 minutes).

    Mais dès que le thread est actif, je n'ai plus la main sur mon application (par exemple pour cliquer sur un bouton).
    Je suppose que c'est à cause de la boucle infinie contenue dans le thread.

    Je suppose que normalement le thread ne devrait pas bloquer de cette manière l'application...
    J'ai ajouté un Sleep(200) dans le while comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DWORD WINAPI myThread(LPVOID arg)
    {
      c_treatment *tr = (c_treatment *)arg;
      while (tr->thread_ok) 
      {
         tr->updateMessage();
         Sleep(200);
      }
      return 0;
    }
    Cela ne bloque plus mon application mais je ne trouve pas cette solution très "propre".

    Qu'en pensez-vous ?
    Merci d'avance pour vos réponse.

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Sleep(0), pas 200.

    Le Sleep(0), sous Windows, termine le quantum de temps et donne la main à la thread suivante. Sans celà, le thread va effectivement prendre 100% du temps CPU (mais il ne va pas t'empêcher de cliquer sur un bouton ; c'est une illusion : tu peux toujours cliquer sur le bouton, c'est juste que c'est plus difficile parce que le thread principal ne récupère pas assez souvent la main).

    Une autre solution est de faire une boucle non pas sur un bool (ce n'est de toute façon pas safe : rien ne te dis que la lecture d'un bool est une opération atomique ; et si ton bool n'est pas volatile, il y a même des chances qu'il ne soit pas lu du tout dans ton thread) mais sur un event (WaitForSingleEvent(hEvent), INFINITE). Un SetEvent() dans le thread principal permet de mettre l'event à VRAI (et donc de débloquer l'attente). Détruire le handle va sortir de de WaitForSingleEvent sur erreur. Pendant l'attente, le thread est garanti de ne prendre pas plus de 0% de temps CPU, donc c'est pas trop mal. Il est aussi garanti que le thread se réveillera au plus vite.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 18
    Par défaut
    Bonjour,

    Merci pour ta réponse.

    Le Sleep(0) ne change rien (ça utilise toujours 100 % du temps CPU).

    Autrement, pour l'autre solution, ce n'est pas plutôt WaitForSingleObject() ?
    Peux-tu me donner un exemple ?

    Merci

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par lika_lika Voir le message
    Bonjour,

    Merci pour ta réponse.

    Le Sleep(0) ne change rien (ça utilise toujours 100 % du temps CPU).
    Ca devrait. Tu as un autre problème autre part.

    Citation Envoyé par lika_lika Voir le message
    Autrement, pour l'autre solution, ce n'est pas plutôt WaitForSingleObject() ?
    Peux-tu me donner un exemple ?

    Merci
    CreateEvent, SetEvent, WaitForSingleObject et CLoseHandle sont les fonctions qui sont nécéssaires à l'utilisation des event sous Windows. Leur fonctionnement est trivial (cf. MSDN), et écrire l'exemple me prendre plus de temps qu'il ne t'en faudra pour les comprendre - donc je vais décliner
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 18
    Par défaut
    Oui, c'est bizarre pour le Sleep(0).
    J'ai donc créé un event:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my_hand = CreateEvent(NULL, FALSE, FALSE, NULL);
    C'est peut-être bête, mais je ne vois pas comment utiliser WaitForSingleObject() dans le thread, j'ai fait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    do {
      tr->updateMessage();
    } while (WaitForSingleObject(tr->my_hand, INFINITE) != WAIT_OBJECT_0);
    Dans cette boucle, on ne rentre qu'une seule fois.
    Et le
    est fait au bout de 30 minutes à peu près.
    Je voudrais que la méthode "updateMessage()" soit appelée en permanence durant ces 30 minutes.

    Merci

  6. #6
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Ce thread a pour but d'envoyer des messages toutes les N secondes (avec N qui varie de 2 à 15).
    C’est idiot, mais je ne vois pas cette partie dans ton code. À la lecture, j’ai plutôt l’impression que tu envoies des messages en permanence (d’où la boucle infinie et l’application qui ne répond plus).

    Pour le sleep(0) dont parle Emmanuel, je pense que c’est un archaïsme datant de windows 3 (!!!) qui n’était pas préemptif : il n’y en a plus besoin de nos jours (peut-être encore dans certains cas, mais je ne les connais pas, ils ne doivent pas être si courants ).

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 18
    Par défaut
    Bonjour,

    La partie de code qui envoie des messages se situe dans la méthode updateMessage() qui va comparer l'heure courante avec une date d'init, et en fonction du résultat, elle envoie un message.

    J'ai réussi à me débrouiller en faisant ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    DWORD WINAPI myThread(LPVOID arg)
    {
      c_treatment *tr = (c_treatment *)arg;
      do
      {
         tr->updateMessage();
      } while (WaitForSingleObject(tr->my_hand, 500) == WAIT_TIMEOUT);
     
      ExitThread(0);
      return 0;
    }
    L'event "my_hand" est un dans l'état "non signalé" avant de lancer le thread.
    Comme ça, la méthode updateMessage() est appelée toutes les 500 ms environ.
    Pour arrêter le thread, je fais:


  8. #8
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Tu consommes toujours de la CPU pour rien, certes beaucoup moins, mais tout de même trop.

    Plutôt que d’attendre 200 ou 500 ms, puis de tester pour voir si tu as un message à envoyer, pourquoi ne mets-tu pas ton thread en attente jusqu’à ce qu’il ait un message à envoyer ? Le calcul n’est pas difficile à faire, et le programme n’en fonctionnera que mieux.

  9. #9
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    J'avais plutôt pensé à utiliser WaitForSingleObjet pour signaler qu'un message devait être traité. Du coup, l'attente de message ne coûte strictement rien.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    while (1) {
        DWORD r = WaitForSingleObject(tr->msg_event, INFINITE);
        // Si l'event a été détruit, on sort de la fonction en erreur. 
        // On peut vérifier ça en testant le code de retour : si l'attente
        // a échoué, alors on peut sortir de notre thread. 
        if (r == WAIT_FAILED || r == WAIT_ABANDONNED)
            break;
        // On ne peut pas avoir WAIT_TIMEOUT avec un timeout == INFINITE,
        // donc la seule alternative à ce stade est WAIT_OBJECT0 : nous avons
        // quelque chose à traiter. 
        tr->updateMessage();
    }
    Tu y gagnes deux choses :

    1/ l'attente d'un message ne coute rien.
    2/ tu n'as pas besoin de deux conditions différentes (qui nécessitent deux synchros différentes) pour transmettre les deux informations "fin du traitement" et "message à traiter".
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

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

Discussions similaires

  1. Utilisation de CreateThread sur Windows
    Par CleeM dans le forum Threads & Processus
    Réponses: 1
    Dernier message: 10/08/2012, 13h52
  2. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  3. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  4. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

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