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

Windows Discussion :

CwinThread et OnIdle


Sujet :

Windows

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut CwinThread et OnIdle
    Bonjour,

    J'ai deux soucis :

    1- J'ai une DLL qui lance un thread via :
    m_pClientThread = (CClientThread*)AfxBeginThread(RUNTIME_CLASS(CClientThread), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);

    Ce thread a pour but de recevoir des données sur un socket et de mettre a jour une structure de portée globale.

    Ca marche bien mais à la fermeture du programme, je veux tuer proprement le thread. Je lui envoie donc un message via:
    :ostThreadMessage(m_pClientThread->m_nThreadID, WM_TERM_THREAD, 0, 0)

    ou m_pClientThread est le pointeur sur le thread et WM_TERM_THREAD un message utilisateur pour signaler au thread qu'il doit se terminer.

    Dans le thread, j'ai un mapping :

    BEGIN_MESSAGE_MAP(CClientThread, CWinThread)
    //{{AFX_MSG_MAP(CClientThread)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    //}}AFX_MSG_MAP
    ON_THREAD_MESSAGE(WM_TERM_THREAD, OnTermThread)
    END_MESSAGE_MAP()

    pourtant, la fonction OnTermThread n'est jamais appelée !
    En fait, :ostThreadMessage me retourne 0 (echec).

    2 - J'ai voulu utiliser la fonction membre (surchargée) OnIdle de ma classe de thread pour mettre ma structure a jour régulièrement, mais elle n'est appelée qu'une à deux fois au démarrage de l'appli. et plus du tout ensuite ...

    ???
    Pour moi c'est assez mystérieux, et j'ai rien trouvé de concluant sur MSDN et internet.
    Une idée ??

    Olivier

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    Ton thread possède-t-il une boucle de messages ?
    Si c'est un thread de travail (worker thread), il n'en possède pas et ne risquera donc pas de recevoir des messages...
    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
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut
    Salut Médinoc!

    Merci de ton aide,

    Oui, mon thread possède à priori une boucle de messages, c'est un thread d'interface MFC.
    J'ai tout de même essayé de mettre :

    PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE );

    pour forcer la création de la boucle dans le constructeur de ma classe de thread, sans résultat.

    Pour ma question concernant OnIdle, c'est résolu : j'avais laissé le paramètre lCount à 0, donc le système d'exploitation ne donnait plus de temps de traitement à OnIdle. en fixan lCount à une valeur non nulle c'est résolu ...

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 528
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 528
    Par défaut
    Ca veux dire quoi précisémment "à la fermeture du programme".

    Si vous attendez trop longtemps, la fenêtre du thread n'existe peut-être plus.

    Pour continuer avec la fixette sur le découplage exécutable-dll, je vous conseil de d'utiliser une fonction "UnInit" qui serait appelé avant le déchargement de la dll (comme une méthode Init au chargement de la dll).
    Vous devez avoir un mécanisme synchrone de fin de programme (PostMessage est un mécanisme éminemment asynchrone) pour arrêter correctement votre programme.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut
    hein ?

    mmm excuse moi bacelar, tu ne te serais pas trompé de message en répondant, je ne vois pas le rapport

    ;-)

    Olivier

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 528
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 528
    Par défaut
    Non.
    Les destructeurs des globales, c'est bien trop tard pour faire le ménage dans les threads car il y déjà eu le déchargement de bon nombres de dll.

    Il faut appeler une fonction de la dll comme "UnInit" par exemple, avant la fin du programme et cette fonction ne rendra la main uniquement quand les threads créés par la dll seront terminés. C'est le seul moyen propre de faire les choses.
    Sinon, vous aller avoir des problèmes de thread tués violemment avec risque d'incohérence de données ou des deadlocks lors du déchargement des dll en fin d'exécution.

  7. #7
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 540
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 540
    Par défaut
    Citation Envoyé par oliver_mpt Voir le message
    hein ?

    mmm excuse moi bacelar, tu ne te serais pas trompé de message en répondant, je ne vois pas le rapport
    Olivier
    1-Y'a un forum MFC
    2-eh ou Bacelar a raison comment charges-tu et décharges-tu la dll ?
    Est-ce que tu appelles bien WaitForSingleObject() ?
    Si tu fais FreeLibrary() quelque part il faut terminer l'exécution du Thread.
    Perso je n'aime pas les BEGIN_MESSAGE_MAP /ON_ avec les macros et cette méthode de "mapping" , je préfère appeler CWnd :: PreTranslateMessage qui gère les messages comme dans un programme basique win32.
    Si la dll ne contient pas de controles genre PushButton je préferrais une dll win32 pure plutot qu'avec MFC..
    MFC c'est bien pour faire des applis fenêtrées UI mais pas trop pour le système

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 68
    Par défaut
    Salut Bacelar,

    merci encore pour ton aide.
    J'ai un peu creusé dans la direction indiquée et j'ai finalement compris pourquoi les messages n'arrivait pas à destination :

    Mon programme est une DLL, qui crée un thread chargé des communications avec un serveur pour mettre à jour une structure. Le thread de com n'est pas tué proprement, car il est tué trop vite...

    Dans mes test, j'appelle ma DLL depuis une application MFC constituée d'une boite de dialogue modale. à la fermeture de la boite de dialogue, le ExitInstance de ma DLL est bien appelé, mais il ne sert à rien que lui essaye de tuer proprement le thread de communication, QUI EST DEJA MORT !
    Il semble que le thread est tué dès que la boite de dialogue rends la main, donc le PostThreadMessage censé demander au thread de se terminer proprement retourne 0 !
    Je ne comprends pas bien pourquoi le thread se termine sans que j'ai le moindre controle dessus ...
    une idée ?

  9. #9
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 528
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 528
    Par défaut
    Etes-vous sur que le thread est déjà mort au moment de l'ExitInstance de la dll?
    Utilisez l'handle du thread pour vérifier que le thread est bien mort, il doit déjà être "signalé" s'il est déjà mort.

    Si c'est vraiment le cas, il suffit d'appeler une fonction "UnInit" de la dll que vous avez précédemment implémenté dans la dll pour faire le ménage. Cet appel à "UnInit" se fera au moment de la destruction de la fenêtre principale.

    Attention, PostMessage n'est pas synchrone, vous devez, dans fonction "UnInit", attendre la fin du thread avec un WaitForSingleObject.

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

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

    Informations forums :
    Inscription : Février 2005
    Messages : 5 528
    Par défaut
    Si vous utilisez les primitives MFC pour créer des threads d'interfaces, il y a fort à parier que les MFC maintiennent une structure avec l'ensemble des threads "MFC" créés et s'en servent lors de la terminaison du programme.

Discussions similaires

  1. Comment Tuer un CWinThread ???
    Par FredKodeur dans le forum MFC
    Réponses: 8
    Dernier message: 29/04/2005, 12h47
  2. [MFC] Pb avec CWinThread
    Par pi05 dans le forum MFC
    Réponses: 1
    Dernier message: 23/03/2005, 11h18
  3. [MFC]creer une classe derivé de CWinThread
    Par psyjess dans le forum MFC
    Réponses: 2
    Dernier message: 18/03/2005, 14h23
  4. Problème avec OnIdle
    Par Francky033 dans le forum DirectX
    Réponses: 2
    Dernier message: 15/01/2005, 00h33
  5. Fermer une application à l'aide de OnIdle
    Par Thierry Rapp dans le forum Composants VCL
    Réponses: 2
    Dernier message: 29/08/2002, 12h44

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