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 :

Gestion de Threads et Visual C++ 2008 Express


Sujet :

Threads & Processus C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut Gestion de Threads et Visual C++ 2008 Express
    Bonjour !

    Je suis nouveau venu à la programmation sur Windows (Vista), et j'utilise Visual C++ Express, version 2008.

    Mon programme s'occupe de gérer la commande de moteurs via le port série. Actuellement, lorsque je clique sur mon bouton Go, la fonction de commande des moteurs démarre, et tout mon programme se retrouve bloqué, or j'aimerais avoir la possibilité de mettre le mouvement en pause, ou de le stopper complètement en cas de problème (ce qui revient au même d'un point de vue de programmation).

    Il me faudrait donc, j'imagine, utiliser du multithreading. Lorsque je clique sur le bouton Go, un nouveau thread démarre et s'occupe du contrôle des moteurs, afin que mon UI reste utilisable pendant ce temps.

    Ma question est la suivante : quelle est la bibliothèque de multithreading la plus adaptée pour Visual C++ Express ? J'ai vu qu'il y en avait une intégrée (afxwin.h) à la version normale de Visual C++, mais j'aimerais si possible ne pas avoir besoin de payer...

    Merci d'avance pour vos réponses !

    Rumpy

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu n'as pas besoin de "bibliothèque" de multithreading sous Windows: L'API système et la C Run-Time Library (CRT) fournissent les fonctions nécessaires.

    En l'occurrence, dans un programme C normal, tu dois utiliser la fonction _beginthreadex() (et transtyper son type de retour en HANDLE pour pouvoir appeler CloseHandle() dessus quand ce sera approprié).

    PS: afxwin.h n'est pas une bibliothèque: C'est l'un des fichiers d'en-tête de la bibliothèque C++ Microsoft Foundation Classes, disponible en effet sur les versions payantes de Visual. Et cette bibliothèque est loin de se limiter au multithread: Elle contient des fonctions de collections, d'interface utilisateur (y compris un framework document/vue), de RTTI, de sérialisation...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    J'ai quand même une nette préférence pour l'utilisation de CreateThread plutôt que _beginthread (ex ou pas), pour ma part... Tu as un exemple sur cette page.

    Je trouve cette API nettement plus pratique que beginthread : d'une part, elle est plus proche des API correspondantes pour les processus, et d'autre part elle donne de bonnes habitudes (à savoir nettoyer tes allocations CRT avant de quitter le thread, et/ou utiliser des pointeurs intelligents).
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Sauf que tu leakes tout ce que la CRT a alloué (et stocké les pointeurs en Thread-Local Storage) d'elle-même et auquel tu n'as pas d'accès manuel...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Sauf que tu leakes tout ce que la CRT a alloué (et stocké les pointeurs en Thread-Local Storage) d'elle-même et auquel tu n'as pas d'accès manuel...
    Encore faut-il utiliser les fonctions de la CRT dans ce thread...

    Or, ce sont justement des fonctions que j'utilise très rarement en thread, où j'ai plutôt tendance à utiliser directement soit des fonctions portables provenant d'une librairie d'abstraction, soit uniquement l'API Win32 (inclus fonctions d'allocation). Le principe étant, bien entendu, de toujours utiliser les fonctions adéquates pour terminer un thread (ne pas utiliser _endthread() si on l'a créé avec CreateThread() et réciproquement).

    Citation Envoyé par MSDN
    If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.
    C'est la seule restriction à l'usage de CreateThread, en fait... Le gros avantage derrière, par contre, c'est que c'est un thread "natif" et que tu parfaitement pouvoir créer ce thread en C++ / Visual, et le terminer par exemple via un programme Delphi ou C++ / GCC sans aucun risque, tout comme un TerminateThread() devient tout d'un coup nettement moins crade si jamais le thread est planté.
    En contexte de DLL et/ou d'intéropérabilité, c'est un critère qui compte, mine de rien.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu ne fais jamais de new et n'utilise pas la STL dans le thread en question, pourquoi pas?
    Mais bon... Et aussi, il faut être sûr qu'aucune fonction d'aucune bibliothèque appelée n'utilise la CRT, sinon leak.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses !

    J'avais trouvé CreateThread(), mais lorsque je lançais mon prog, je ne pouvais pas contrôler mon UI pendant l'exécution de la fonction de contrôle des moteurs, et à la fin de cette fonction, Windows tue mon prog en disant "Pour protéger l'ordinateur, la prévention de l'exécution des données a fermé MonProg.exe.". A quoi cela est-il dû ?

    Pour _beginthreadex(), je n'arrive pas à compiler. Il me dit "error C3867: &'CIC1::Form1::executeReceip'*: liste d'arguments manquante dans l'appel de fonction*; utilisez 'CIC1::Form1::executeReceip' pour créer un pointeur vers membre". Je ne comprends pas pourquoi, car mon appel de la fonction _beginthreadex() est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    threadHandle = (HANDLE)_beginthreadex(NULL, 0, CIC1::Form1::executeReceip, NULL, 0, &threadID);
    avec la fonction executreReceip() définie comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void executeReceip(void)
    En gros, j'aimerais que mon programme soit comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void goButtonClicked(void){
        // lancement du thread de contrôle des moteurs (fonction executeReceip())
    }
     
    void executeReceip(void){
        // contrôle des moteurs
    }
     
    void stopButtonClicked(void){
        // arrêt des moteurs et du thread
    }
    Mon thread ne serait pas lancé depuis la fonction main(), est-ce que ça pourrait poser problème ?

    (Désolé pour mes questions de noob et mes erreurs de termes, c'est la première fois que je fais un programme aussi "complexe" et que je touche à Windows )

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    executeReceip doit être une fonction ou une méthode statique et la signature
    c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static void executeReceip(void *)

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Plus précisément, avec _beginthreadex(), la signature doit être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static unsigned int __stdcall executeReceip(void *);
    Le paramètre passé doit être le pointeur vers un objet de la classe (ou une structure contenant le pointeur vers l'objet) si tu veux pouvoir invoquer des fonctions membres non-statiques dessus.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Oups, j'avais pas vu le "ex" de .

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    J'ai modifié ma fonction comme vous me l'avez dit, mais j'ai maintenant les erreurs et warning suivants lors de la compilation :

    warning C4441: convention d'appel de '__stdcall ' ignorée*; '__clrcall ' utilisé à la place

    error C2665: '_beginthreadex'*: aucune des 2 surcharges n'a pu convertir tous les types d'arguments

    peut être 'uintptr_t _beginthreadex(void *,unsigned int,unsigned int (__stdcall *)(void *),void *,unsigned int,unsigned int *)'

    ou 'uintptr_t _beginthreadex(void *,unsigned int,unsigned int (__clrcall *)(void *),void *,unsigned int,unsigned int *)'

    lors de la tentative de mise en correspondance de la liste des arguments '(int, int, overloaded-function, int, int, DWORD *)'

    Ma fonction est :
    static unsigned int __stdcall executeReceip(void*)

    et mon appel :
    threadHandle = (HANDLE)_beginthreadex(NULL, 0, CIC1::Form1::executeReceip, NULL, 0, &threadID);

    Je dois avouer que je ne comprends pas d'où viennent ces erreurs...

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    T'es en C++/CLI ?
    "executeReceip" est-elle une méthode d'une classe managée ("ref class")?

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    J'ai créé mon projet avec Visual C++ Express, en choisissant CLR puis Application Windows Form. Je ne sais pas si ça répond à ta première question ?

    Ma fonction executeReceip est dans le même fichier que où ma fenêtre est créée (Form1.h) et donc où la fonction appelée lors du clic sur le bouton se trouve.

    Est-ce que c'est assez clair ?

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu as un Form1.h, c'est que tu programmes pour le framework .Net.

    Dans ce cas, tu n'utilises pas les bonnes fonctions de multithreading; tu dois utiliser les classes appropriées du Framework (comme System::Threading::Thread).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Dans les options du projet, j'ai :

    Dans "Propriétés de configuration / Général - Prise en charge du Common Language Runtime", l'option sélectionnée est "Prise en charge pure du CLR MSIL (/clr:pure)"

    Dans "Propriétés de configuration / C/C++ / Génération de code - Bibliothèque runtime", l'option sélectionnée est "DLL multithread (/MD)".

  16. #16
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    C'est donc du C++/CLI, il faut donc utiliser, de préférence pour la simplicité, les primitives .NET.
    Voir la réponse de Médinoc.

  17. #17
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Si tu ne fais jamais de new et n'utilise pas la STL dans le thread en question, pourquoi pas?
    En général, c'est le thread parent qui alloue tout, passe la structure au thread, qui recopie (bovinement) les données sur sa pile si elles sont volatiles, ou garde au contraire la référence sur les données passées par le parent.

    Citation Envoyé par Médinoc Voir le message
    Mais bon... Et aussi, il faut être sûr qu'aucune fonction d'aucune bibliothèque appelée n'utilise la CRT, sinon leak.
    Ce qui est toujours le cas si tu n'utilises que l'API Win32, ou des librairies basées exclusivement sur Win32.

    Certes, c'est un cas spécifique, mais en général je ne crée que deux sortes de thread : soit des threads liés à l'interface / système (=> j'utilise la fonction adéquate, par exemple un CWinThread), soit ce sont des threads de communication / calcul (=> API Win32 exclusivement, avec ou sans couche de portage).


    Reste effectivement que ces fonctions ne sont de toutes façons pas à utiliser dans un contexte .NET ou C++/CLI, bien entendu.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  18. #18
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Si tu as un Form1.h, c'est que tu programmes pour le framework .Net.

    Dans ce cas, tu n'utilises pas les bonnes fonctions de multithreading; tu dois utiliser les classes appropriées du Framework (comme System::Threading::Thread).
    Merci à tous ! Même si j'ai pas toujours compris tous les points de vos réponses, c'est super cool
    Ça marche super maintenant, merci merci beaucoup !
    Enfin, il me reste plus qu'à implémenter mes fonctions correctement ^^

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Doc + exemple de "system.threading.thread"
    http://msdn.microsoft.com/fr-fr/libr...ng.thread.aspx

  20. #20
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Septembre 2009
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Yep merci, j'avais trouvé la doc et les exemples, et mon code fonctionne, c'est cool !

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/03/2008, 10h30
  2. System.Data.Linq.Mapping sous Visual C# 2008 Express ?
    Par Papy214 dans le forum Accès aux données
    Réponses: 6
    Dernier message: 26/02/2008, 10h23
  3. Visual Studio 2008 Express sur Pc non connecté
    Par jncoffy dans le forum Général Dotnet
    Réponses: 2
    Dernier message: 22/02/2008, 13h58
  4. Visual Studio 2008 Express Edition, demande d'information ?
    Par Mon_Compte dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 26/01/2008, 20h57
  5. Visual C# 2008 Express + MSDN : doc du framework manquante
    Par tomlev dans le forum Général Dotnet
    Réponses: 7
    Dernier message: 21/09/2007, 14h05

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