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 :

Thread et communication de variables


Sujet :

MFC

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut Thread et communication de variables
    Bonjour,

    Je suis bloqué dans le développement d'une application MFC (je suis débutant).

    Enfaite, j'ai une classe contenant ma boite de dialogue, avec boutons et zone d'édition et une autre classe contenant une machine à état (envoi/réception de donnée en fonction de l'état via port série).

    A l'appui sur un bouton, je créer un thread avec AfxBeginThread qui démarre ma machine à état. Ainsi, je peux continuer à utiliser ma boite de dialogue sans qu'elle soit bloquée par ma machine à état.

    Le problème, c'est que je n'arrive pas à communiquer les états (sous forme de CString ou int peu importe) de ma machine à état vers ma boite de dialogue pour pouvoir afficher l'état en temps réel dans une zone d'édition.

    Comment je peux faire?

    StateMachine.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
     
    void StateMachine::Etats (int state)
    {
        while (state != x)
        {
            switch (state)
            {
                case 0:
                ...
                case 1:
                ...
            }
        }
    }
    Dialog.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
     
    StateMachine *stateMachine1 = new StateMachine;
     
    void Dialog::OnClickedStart
    {
        ...
        AfxBeginThread(MyThread,0);
    }
     
    UINT MyThread(LPVOID Param)
    {
        ...
        stateMachine1->Etats(0);
        ...
    }

  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
    Pour communiquer vers un thread d'UI avec l'API Win32 ou MFC, généralement on utilise SendMessage() ou PostMessage(), selon qu'on ait besoin ou non d'être synchrone. L'avantage d'un appel synchrone est qu'on n'a pas besoin de transférer la "propriété" d'une variable allouée dynamiquement, vu que le traitement du message sera fini avant que SendMessage() retourne.
    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
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Merci beaucoup pour cette réponse , je vais essayer ça!

  4. #4
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Bon alors, j'ai bien essayé SendMessage() et PostMessage().

    Malheureusement, dans les deux cas, j'ai :
    - Exception levée à 0x004016DE dans VC_Sample.exe : 0xC0000005 :Violation d'accès lors de la lecture de l'emplacement 0x00000020.



    StateMachine.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
     
    StateMachine::StateMachine()
    {
     
    }
     
    void StateMachine::Etats (int state)
    {
        Dialog *pDLg = (Dialog *) GetParent(HWND_BROADCAST);
     
        while (state != x)
        {
            switch (state)
            {
                case 0:
                    pDLg -> SendMessage(WM_PROC_CONTROL2, (WPARAM)"test", 0);
                case 1:
                ...
            }
        }
    }
    Dialog.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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
     
    StateMachine *stateMachine1 = new StateMachine;
     
    Dialog::Dialog(CWnd* pParent) : CDialog(Dialog::IDD, pParent)
    {
     
    }
     
    void Dialog::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
    }
     
    BEGIN_MESSAGE_MAP(Dialog, CDialog)
        ...
        ON_MESSAGE(WM_PROC_CONTROL2, OnProcControl2) //Il existe un autre ProcControl qui utilise une dll
     
    END_MESSAGE_MAP()
     
    LRESULT Dialog::OnProcControl2(WPARAM wParam, LPARAM lParam)
    {
        CString *pstr = (CString*)wParam;
        return (LRESULT)0;
    }
     
    void Dialog::OnClickedStart
    {
        ...
        AfxBeginThread(MyThread,0);
    }
     
    UINT MyThread(LPVOID Param)
    {
        ...
        stateMachine1->Etats(0);
        ...
    }
    Une idée?

    A+

  5. #5
    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
    Que retourne GetParent(HWND_BROADCAST)?
    PS: Attention à ne pas confondre CWnd::GetParent() qui retourne un CWnd*, et ::GetParent(HWND) qui retourne un HWND. Dans aucun des deux cas la valeur retournée ne devrait être castable en Dialog*...
    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.

  6. #6
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Merci beaucoup, ça m'a mis sur la piste pour résoudre le problème!

    Maintenant, ça fonctionne impeccable.

    StateMachine.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
    StateMachine::StateMachine()
    {
     
    }
     
    void StateMachine::Etats (int state)
    {
        CString* state0 = new CString (_T("State 0"));
        CString* state1 = new CString (_T("State 1"));
        ...
     
        while (state != x)
        {
            switch (state)
            {
                case 0:
                    AfxGetMainWnd() -> SendMessage(WM_PROC_CONTROL2, (WPARAM)state0, 0);
                case 1:
                    AfxGetMainWnd() -> SendMessage(WM_PROC_CONTROL2, (WPARAM)state1, 0);
                ...
            }
        }
    }
    Dialog.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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    StateMachine *stateMachine1 = new StateMachine;
     
    Dialog::Dialog(CWnd* pParent) : CDialog(Dialog::IDD, pParent)
    {
     
    }
     
    void Dialog::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
    }
     
    BEGIN_MESSAGE_MAP(Dialog, CDialog)
        ...
        ON_EN_CHANGE(IDC_EDIT_LOG, &Dialog::OnEnChangeEditLog)
        ON_MESSAGE(WM_PROC_CONTROL2, OnProcControl2) //Il existe un autre ProcControl qui utilise une dll
     
    END_MESSAGE_MAP()
     
    LRESULT Dialog::OnProcControl2(WPARAM wParam, LPARAM lParam)
    {
        CString *pstr = (CString*)wParam;
        CString& Temp = *pstr;
     
        CString strTmp;
        CString strTxtLog;
        GetDlgItemText(IDC_EDIT_LOG, strTxtLog);
     
        strTmp.Format(_T("") + Temp + SZ_CRLF);
     
        strTxtLog += strTmp;
     
        SetDlgItemText(IDC_EDIT_LOG, strTxtLog);
     
        ((CEdit*)GetDlgItem(IDC_EDIT_LOG)->SetSel(strTxtLog.GetLength(), strTxtLog.GetLength());
     
        return (LRESULT)0;
    }
     
    void Dialog::OnClickedStart
    {
        ...
        AfxBeginThread(MyThread,0);
    }
     
    UINT MyThread(LPVOID Param)
    {
        ...
        stateMachine1->Etats(0);
        ...
    }
    Dernière question et ce sera bon pour moi je pense :
    - Y-a-t-il un truc plus "sexy" que de faire ça :
    CString* state0 = new CString (_T("State 0"));
    CString* state1 = new CString (_T("State 1"));
    ...

  7. #7
    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
    Déjà, vu que tu utilises SendMessage() qui est synchrone, tu pourrais simplement faire ceci:
    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
    18
    19
    20
    21
    22
    23
    //Ici on prend directement un LPCTSTR, 
    //vu qu'on ne le modifie pas et qu'on ne l'utilise plus une fois que SendMessage() a retourné
    void AfficherTexte(LPCTSTR texte)
    {
    	AfxGetMainWnd()->SendMessage(WM_PROC_CONTROL2, reinterpret_cast<WPARAM>(texte), 0);
    }
     
    LRESULT Dialog::OnProcControl2(WPARAM wParam, LPARAM lParam)
    {
    	//Changement pour prendre en compte le fait de passer le texte sous forme de LPCTSTR
    	LPCTSTR texte = reinterpret_cast< LPCTSTR >(wParam);
     
    	//Note: le GetDlgItem() n'est peut-être pas nécessaire, si la textbox est déjà une variable membre.
    	CEdit* textBox = static_cast< CEdit* >(GetDlgItem(IDC_EDIT_LOG));
     
    	//Technique spéciale pour ajouter du texte à la fin d'une textbox:
    	//On sélectionne juste la fin, puis on la remplace par le texte voulu
    	int length = textBox->GetWindowTextLength();
    	textBox->SetSel(textBox, textBox)
    	textBox->ReplaceSel(texte);
     
    	return 0L;
    }
    Avec un PostMessage() ce serait plus compliqué, à cause du transfert de responsabilité.
    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.

  8. #8
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2018
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2018
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Okeeey ça marche impeccable

    Maintenant je voudrais faire la même chose dans l'autre sens, c'est à dire communiquer à partir d'une gestionnaires d'évènement de mon Dialog vers mon thread en cours, mais encore une fois ça casse tout

    StateMachine.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
    StateMachine::StateMachine()
    {
     
    }
     
    void StateMachine::Etats (int state)
    {
        ...
     
        while (state != x)
        {
            switch (state)
            {
                case 0:
                ...
                ////////////////////// J'attends de recevoir "OK1" à partir de ma gestionnaire d'evnt "OnProcControl" pour passer à case 1 //////////////////////
                case 1:
                ...
                ////////////////////// J'attends de recevoir "OK2" case 2 //////////////////////
                ...
            }
        }
    }
    Dialog.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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    StateMachine *stateMachine1 = new StateMachine;
     
    Dialog::Dialog(CWnd* pParent) : CDialog(Dialog::IDD, pParent)
    {
     
    }
     
    void Dialog::DoDataExchange(CDataExchange* pDX)
    {
        CDialog::DoDataExchange(pDX);
    }
     
    BEGIN_MESSAGE_MAP(Dialog, CDialog)
        ...
        ON_EN_CHANGE(IDC_EDIT_LOG, &Dialog::OnEnChangeEditLog)
        
        ON_MESSAGE(WM_PROC_CONTROL, OnProcControl) // Le proc control qui communique avec une DLL
        
        ON_MESSAGE(WM_PROC_CONTROL2, OnProcControl2)
     
    END_MESSAGE_MAP()
    
    LRESULT Dialog::OnProcControl(WPARAM aParam, LPARAM aParam)
    {
        CString strTmp;
        
        const int MAX_RECEIVE = 1024; // Nombre maximal d'octets de tampon de réception
    
        TCHAR szReceive[MAX_RECEIVE];
    
        memset ( szReceive, 0, sizeof(szReceive) );
    
        // Reçu via l'application xxx à travers la DLL
        int nRecCount = RecieveCommand( szReceive, sizeof(szReceive) ); ////////////////////// Information reçu par la DLL que j'affiche ensuite dans mon Log //////////////////////
    
        CString strTxtLog
        GetDlgItemText(IDC_EDIT_LOG, strTxtLog);
    
        if( 0 < nRecCount )
        {
            strTmp.Format( _T("*[Receive]%s%s"), szReceive, SZ_CRLF );
            strTxtLog += strTmp;
        }
        else
        {
            
            strTmp.Format( _T("*[Receive]Error[No received data.)%s"), SZ_CRLF );
            strTxtLog += strTmp;
        }
        SetDlgText( IDC_EDIT_LOG, strTxtLog );
        ((CEdit*)GetDlgItem(IDC_EDIT_LOG))->SetSel( strTxtLog.GetLength(), strTxtLog.GetLength() );
    
        ////////////////////// Transmettre strTxtLog à mon thread //////////////////////
    
        return (LRESULT)0;
    
    }
     
    LRESULT Dialog::OnProcControl2(WPARAM wParam, LPARAM lParam)
    {
        ...
    }
     
    void Dialog::OnClickedStart
    {
        ...
        AfxBeginThread(MyThread,This);
    }
     
    UINT MyThread(LPVOID Param)
    {
        ...
        stateMachine1->Etats(0);
        ...
    }
    Voilou

    A+

  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
    Vu que le thread de travail n'a pas de boucle de messages, tu ne peux pas utiliser SendMessage() pour communiquer avec. Par contre, si tu dois juste échanger des "OK1" et "OK2", tu peux utilise deux Events. Renseigne-toi sur les fonctions CreateEvent(), SetEvent(), WaitForSingleObject() et CloseHandle().
    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.

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

Discussions similaires

  1. OOP : communication des variables fille -> mère
    Par Pleinpopossum dans le forum Langage
    Réponses: 9
    Dernier message: 02/04/2008, 16h37
  2. Gestion des threads de communication TCP/IP
    Par Daminus dans le forum Delphi
    Réponses: 6
    Dernier message: 01/12/2006, 13h37
  3. Réponses: 2
    Dernier message: 29/08/2006, 01h07
  4. [MFC] Thread de communication et Dialog Data Exchange
    Par Philippe320 dans le forum MFC
    Réponses: 4
    Dernier message: 20/05/2006, 17h07
  5. Thread C++ C et variables.....
    Par panda_fonfon dans le forum MFC
    Réponses: 4
    Dernier message: 28/04/2006, 15h06

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