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

MFC Discussion :

[MFC] Multithreading, Thread Worker


Sujet :

MFC

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    150
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 150
    Points : 111
    Points
    111
    Par défaut [MFC] Multithreading, Thread Worker
    Bonjour,

    J'ai un probléme avec le multithreading MFC, je voudrai qu'un thread externe à ma boite de dialogue puisse appeler des fonctions de cette boite de dialogue.

    En faites je voudrai que ma boite de dialogue lance un thread worker qui puisse afficher des informations via la boite de dialogue dans un simple label par exemple, pour cela il y a une méthode publique Echo(char *texte) dans ma boite de dialogue qui permet d'afficher du texte.

    CTestDlg est composé d'une classe Clol, lorsque j'appuie sur le bouton ok, Clol lance un thread qui va afficher quelque chose dans un label de CTestDlg toutes les secondes en appelant la fonction Echo, j'ai utilisé le handle de la boite de dialogue et utilisé la fonction FromHandle() pour récupérer CTestDlg dans le thread externe mais ca ne fonctionne pas, ca plante dans la fonction Echo() de CTestDlg, au niveau de la ligne loltexte.SetString(buff) :
    Exception non gérée à 0x7832c55f (mfc80ud.dll) dans Test.exe : 0xC0000005: Violation d'accès lors de la lecture de l'emplacement 0xf3d030fd.

    lol.cpp
    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
     
    #include "stdafx.h"
    #include "lol.h"
    #include "TestDlg.h"
     
    HWND Clol::hwnd = 0;
     
    void Clol::Start(){
    	AfxBeginThread(Clol::Thread,NULL);
    }
     
    UINT Clol::Thread(LPVOID param){
    	char text[20];
     
    	CTestDlg* la = (CTestDlg*)CWnd::FromHandle(Clol::hwnd);
     
    	for(int i=0;i<10;i++){
    		sprintf(text,"Ok%d",i);
    		la->Echo(text);
    		Sleep(1000);
    	}
     
    	return 0;
    }
    CTestDlg.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #include "lol.h"
    // boîte de dialogue CTestDlg
    class CTestDlg : public CDialog
    {
    [...]
    public:
            Clol a;
    	CString loltexte;
    	void Echo(char * txt);
    [...]
    CTestDlg.cpp
    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
    [...]
    
    void CTestDlg::Echo(char * texte){
    	wchar_t buff[500];
    	mbstowcs(buff,texte,500);
            //Ca plante ici
    	loltexte.SetString(buff);
    	UpdateData(false);
    }
    
    
    void CTestDlg::OnBnClickedOk()
    {
    	a.hwnd = GetSafeHwnd();
    	a.Start();
    }
    [...]

    EDIT: Je ne peux pas passer par le système des messages, ca fonctionne très bien mais je ne peux pas utiliser cette méthode car dans le cas réel de mon problème (ici il s'agit d'une version simplifié), Echo retourne une valeur que je dois récupérer.

  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
    C'est pourtant simple:
    Code C++ : 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
    void Clol::Start(CTestDlg *pDlg) {
    	AfxBeginThread(Clol::Thread, pDlg);
    }
     
    UINT Clol::Thread(LPVOID param) {
    	char text[20];
     
    	CTestDlg * la = static_cast< CTestDlg* >(param);
     
    	for(int i=0;i<10;i++){
    		sprintf(text,"Ok%d",i);
    		la->Echo(text);
    		Sleep(1000);
    	}
     
    	return 0;
    }
    Pourquoi se compliquer la vie avec des FromHandle() et des variables globales/statiques quand on peut juste passer un paramètre au thread ?

    Edit: Le système des messages permet également de retourner une valeur si on utilise SendMessage(). Et Windows se charge de la synchronisation pour toi...
    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 régulier
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    150
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 150
    Points : 111
    Points
    111
    Par défaut
    Pourquoi faire compliquer ? Car j'ai lu ca : http://msdn2.microsoft.com/fr-fr/lib...2e(VS.80).aspx

    Si on procéde à ta facon ca plante d'une manière différente, on a le droit à un avertissement qui nous dit d'utiliser les handle, puis FromHandle() et non les adresses des objets , j'avais procédé de cette manière pour commencer, après j'ai appris qu'il fallait le faire a partir des handles.


    EDIT :
    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
     
    		ASSERT((CWnd*)p == this);   // must be us
     
    		// Note: if either of the above asserts fire and you are
    		// writing a multithreaded application, it is likely that
    		// you have passed a C++ object from one thread to another
    		// and have used that object in a way that was not intended.
    		// (only simple inline wrapper functions should be used)
    		//
    		// In general, CWnd objects should be passed by HWND from
    		// one thread to another.  The receiving thread can wrap
    		// the HWND with a CWnd object by using CWnd::FromHandle.
    		//
    		// It is dangerous to pass C++ objects from one thread to
    		// another, unless the objects are designed to be used in
    		// such a manner.

  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
    Ceci n'a aucun effet, car la carte des objets CWnd vers HWND est locale pour le thread principal
    C'est absurde! Il n'y a pas de carte CWnd--> HWND, puisque la CWnd CONTIENT le HWND correspondant. Une carte HWND vers CWnd je comprendrais, mais là on n'est pas censé en avoir besoin...

    Si on procéde à ta facon ca plante d'une manière différente, on a le droit à un avertissement qui nous dit d'utiliser les handle, puis FromHandle() et non les adresses des objets
    Tu veux dire, une erreur d'assertion ?

    Edit: OK, j'ai compris. La classe CWnd vérifie un truc dont on n'a pas besoin...

    Bon, J'ai compris ton erreur en tout cas avec FromHandle() : L'objet créé pour ce thread n'est pas un objet CTestDlg, mais un objet CWnd.
    Tu devrais essayer de créer un objet CTestDlg et appeler sa méthode Attach() sur le HWND (quitte à appeler Detach() avant la fin du 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.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    150
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 150
    Points : 111
    Points
    111
    Par défaut
    Oui mais je vais utiliser le systéme des messages pour finir, ca à l'air bien plus simple, en faites je ne savais pas qu'on pouvait récupérer la valeur de retour d'un SendMessage.

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

Discussions similaires

  1. [MFC] CFormView, Thread et rafraichissement
    Par Philippe299 dans le forum MFC
    Réponses: 6
    Dernier message: 08/09/2005, 15h18
  2. [MFC] classe thread
    Par Joeleclems dans le forum MFC
    Réponses: 13
    Dernier message: 24/05/2005, 14h31
  3. [MFC] multithread, communication père<->fils
    Par Joeleclems dans le forum MFC
    Réponses: 19
    Dernier message: 19/05/2005, 10h31
  4. [MFC] dialog & thread & progressbar
    Par Tigris94 dans le forum MFC
    Réponses: 4
    Dernier message: 05/04/2005, 15h51
  5. [MFC] UpdateData() + thread
    Par MadChris dans le forum MFC
    Réponses: 6
    Dernier message: 03/06/2004, 20h55

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