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 :

impossible d'utiliser un HWND parent dans un thread


Sujet :

Windows

  1. #1
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut impossible d'utiliser un HWND parent dans un thread
    Je n'arrive pas a utiliser un HWND passé parametre à un thread en tant que parent d'une fenetre dans ce thread.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* Point d'entrée du thread */
    DWORD WINAPI WaitingDlg::ThreadProc( LPVOID lpParameter)
    	{
    	HWND hDlg = ( HWND )lpParameter;
    	MessageBox( hDlg, "thread demarré", "info", MB_OK );
    	return 0;
    	}
     
    /* Méthode qui lance le thread */
    void WaitingDlg::doModal(HWND hDlg) {
    	MessageBox( hDlg, "thread demarré", "info", MB_OK );
    	threadH=CreateThread( NULL, 0, ThreadProc, hDlg, 0, &threadId );
    	}
    La messsage box dans la methode doModal() s'affiche correctement.
    Mais l'éxecution se bloque (plus rien ne se passe et rien n'est affiché) sur la message box de ThreadProc().
    En revanche si je ne met pas de parent pour la message box de ThreadProc(), ça marche très bien.

    J'aimerai savoir si quelqu'un a déjà rencontré des problemes de ce genre.
    Merci d'avance

  2. #2
    Membre régulier
    Inscrit en
    Juillet 2003
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 140
    Points : 76
    Points
    76
    Par défaut
    voila comment il faut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DWORD WINAPI WaitingDlg::ThreadProc( LPVOID lpParameter) 
       { 
       HWND hDlg = ( HWND )lpParameter; 
       MessageBox( hDlg, "thread demarré", "info", MB_OK ); 
       return 0; 
       } 
      
    /* Méthode qui lance le thread */ 
    void WaitingDlg::doModal(HWND hDlg) { 
       MessageBox( hDlg, "thread demarré", "info", MB_OK ); 
       threadH=CreateThread( NULL, 0, ThreadProc, (LPVOID)hDlg, 0, &threadId ); 
       }

  3. #3
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 750
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 750
    Points : 10 667
    Points
    10 667
    Billets dans le blog
    3
    Par défaut
    Compare la valeur de hDlg passée et reçue (trace l'exécution au debugger).

  4. #4
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut
    En fait je viens de me rendre compte que mon problème est plus compliqué que ça.
    J'essais de faire une une boite de dialogue pour faire patienter l'utilisateur pendant des calculs. Un thread a part doit donc creer cette boite de dialogue.

    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
    volatile bool ready;
    HANDLE threadH;
    DWORD threadId;
    
    /* point d'entree du thread */
    DWORD WINAPI WaitingDlg::ThreadProc( LPVOID lpParameter)
    {
    	HWND hDlg=(HWND)lpParameter;
    	HWND dialogHandle=CreateDialog(hInst, (LPCTSTR)IDD_WAITING, hDlg , (DLGPROC)WaitingDlg::callBack);
    	ShowWindow(dialogHandle,SW_SHOW);
    	ready=true;
    	MSG msg;
    	while(	GetMessage(&msg,NULL,0,0)==TRUE ){
    		if( msg.message==ID_END_DIAG ){
    			EndDialog(dialogHandle, 0);
    			return 0;
    		}
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return 0;
    }
    
    /* demarage du thread */
    void WaitingDlg::doModal(HWND hDlg){
    	ready=false;
    	threadH=CreateThread(NULL,0,ThreadProc,(LPVOID)hDlg,0,&threadId);
    }
    
    /* arret du thread */
    void WaitingDlg::stop(void){
    	if( threadH==NULL )
    		return;
    	while( !ready )
    		Sleep(5);
    	PostThreadMessage(threadId,ID_END_DIAG,0,0);
    	CloseHandle(threadH);
    	}
    La variable ready permet d'attendre que le thread soit dans la partie gestion de message avant d'envoyer le message d'arret du thread (dans la methode stop).

    Ce code marche bien si je ne donne pas de parent a la boite de dialogue.
    ( la boite de dialogue s'affiche et disparait a la demande)

    Mais des que je donne un parent a cette boite de dialogue. Le thread principale se bloque dans la boucle while( !ready ). Et le thread censé afficher la boite de dialogue se bloque sur la ligne du CreateDialog().
    J'ai verifié, le HWND dans le point d'entree du thread est le meme que celui dans la methode doModal() et ce pointeur est valide.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 77
    Points : 83
    Points
    83
    Par défaut
    il faut remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    while( !ready ) 
          Sleep(5);
    par un

    WaitForSingleObject(threadH, INFINITE) ;

  6. #6
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut
    si je remplace mon while( !ready ) par un WaitForSingleObject() , je vais attendre que le thread se termine. Or la ligne qui arrete le thread est juste après le while() => le thread ne se terminera pas et je vais rester bloqué sur le WaitForSingleObject()

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 77
    Points : 83
    Points
    83
    Par défaut
    j'ai pas tres bien vu comment WaitingDlg::stop est appelé

  8. #8
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut
    Je n'ai pas mis l'appel à la methode dans mon exemple.
    Mais l'utilisation du code pourrais etre de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ...
    WaitingDlg wd;
    wd.doModal ( hwnd );
    ...
    // code prenant du temps
    ...
    wd.stop();

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 77
    Points : 83
    Points
    83
    Par défaut
    si la fonction stop est appelée aprés le code qui prend du temps, je ne saisis pas pourquoi elle fait une boucle avec des sleep sur ready

  10. #10
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut
    Si le code ne prend pas assez de temps, le thread n'a pas le temps d'afficher la fenetre, que la methode stop() est déjà appelé => le thread n'est pas encore dans sa partie gestion de messages et ne traite pas le message envoyé par la méthode stop() => le thread reste en vie indefiniment

  11. #11
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 750
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 750
    Points : 10 667
    Points
    10 667
    Billets dans le blog
    3
    Par défaut
    Mets ready a false après avoir créé le thread.
    Mais cette variable ready n'est pas ce qu'il y a de plus propre. Oriente toi vers des mécanismes spécifiques, tels que les Mutex ou les sections critiques.
    Dans ton cas je trouve aussi plus simple de lancer le calcul dans un nouveau thread et non pas le dialogue. Ton thread de calcule reçoit en paramètre le HWND de la fenêtre de progression et lui envoie un message sur son avancement

  12. #12
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut
    J'utilisise cette boite de dialogue plusieurs fois pour des calculs différents. Donc il faudrai passer un pointeur de fonction et une structure pour les données... ce qui ne facilite pas forcement l'utilisation de la boite de dialogue.

    D'autre part, meme si il n'est pas trés propre, ce code marche si je met le parent de la boite de dialogue a NULL. Ce que je ne comprend pas c'est le blocage quand je lui passe un parent.
    Y aurait-il parfois impossibilité d'avoir un parent appartenent a autre thread ?

  13. #13
    Membre du Club
    Inscrit en
    Novembre 2002
    Messages
    51
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 51
    Points : 57
    Points
    57
    Par défaut
    J'ai compris que ce que je voulais faire était impossible.
    J'ai fini par essayer le meme code en Java et j'ai eu le meme probleme.
    Mais connaissant mieu les méchanisme des Thread en Java j'ai crompris le probleme et je suppose que c'est le meme avec l'API Win.

    En java il y a 1 thread qui est dédié à la gestion des messages graphiques : l'Event Dispatch Thread (EDT).
    Voila donc ce que j'essayai de faire :

    1) Je récupéré un message de l'utilisateur et entre dans l'EDT.
    2) Dans l'EDT j'ai un gros calcul a faire donc je creer un Thread a qui je demande d'afficher une boite de dialogue modale.
    3) Dans l'EDT, une fois le calcule terminé je m'assure (avec une boucle d''attente) que la boite de dialogue soit affiché avant de la fermer.

    Or je peu toujours attendre quelle soit affiché car l'EDT est dans la boucle d'attente et thread que j'ai créé attend que son message (sa demande d'affichage soit traité) par l'EDT.
    Je me retrouve donc en interblocage.

    Donc je pense que c'est le meme probleme qui se pose sous Windows.
    Je suppose que Windows doit avoir un thread dédié à la gestion des événements graphiques. Si quelqu'un peu confirmer!

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

Discussions similaires

  1. Impossible d'afficher une Alert Dialog dans un thread!
    Par User Name dans le forum Composants graphiques
    Réponses: 8
    Dernier message: 07/01/2013, 23h24
  2. Réponses: 6
    Dernier message: 08/11/2010, 08h25
  3. Réponses: 3
    Dernier message: 31/12/2009, 17h49
  4. Réponses: 1
    Dernier message: 16/10/2007, 17h58
  5. impossible d'utiliser ma fonction dans un insert
    Par caramel dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 10/04/2003, 15h04

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