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

C++/CLI Discussion :

Threads et TextBox


Sujet :

C++/CLI

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    3
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 3
    Par d�faut Threads et TextBox
    Bonjour,

    Tout d'abord je voudrai remercier la communaut� de developpez.net o� j'ai pu trouver des solutions � la plupart de mes probl�mes rien qu'en parcourant les forums, les FAQ et les tutoriaux depuis plus d'un an maintenant.

    Je r�alise en ce moment un projet sous visual studio C++ 2008 bas� sur une windows form sens�e afficher des donn�es re�ues via un p�riph�rique externe (type port s�rie) dans une textBox. Il y a donc un thread (n�1) consacr� aux contr�les de la windows Form et un autre thread (n�2) qui g�re les communications avec le p�riph�rique.

    Lorsqu'une trame est re�ue par le thread n�2 je ne peux pas directement l'�crire dans la textBox de mon interface. J'ai donc mis en place un delegate pour pouvoir acc�der aux routines de l'interface graphique. Il est d�clar� dans un .h commun � tout le projet :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    delegate void Ecrire(void);
    Le code � ex�cuter pour �crire dans la textbox est d�crit dans la classe de la windows form(Projet::Form1). Pour l'instant je veux juste afficher OK � chaque r�ception d'une trame:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    public: void EcrireTextBox(void)
    		{
    			textBox1->AppendText("OK");
    		}
    Enfin, dans le fichier .cpp contenant les fonctions bas de niveau de communication avec le port s�rie je fais appel au d�l�gu� pour acc�der � EcrireTextBox :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    Projet::Form1 ^ pnt = gcnew Projet::Form1;
    Ecrire ^ delegue = gcnew Ecrire(pnt, &Projet::Form1::EcrireTextBox);
    delegue->Invoke();
    Quand je met tout �a en debug je vois que lorsqu'une trame est re�ue je rentre bien dans la fonction "EcrireTextBox" et son code est ex�cut�. Par contre rien ne s'affiche dans la TextBox. En observant les outils de debug j'ai vu que le programme restait toujours dans le thread n�2 ce qui, pour moi, explique qu'il n'y a aucun effet sur la textBox (g�r�e par le thread n�1).

    Comment puis-je redonner la main � l'interface graphique (thread n�1) juste le temps de modifier la textbox?

    Merci d'avance

  2. #2
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 64
    Localisation : France

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par d�faut
    Bonjour

    Ton probl�me est plus un probl�me .net qu'un probl�me C++.
    Il serait peut �tre pr�f�rable de l'exposer dans le forum .Net


    Sinon, et � vue de nez (bien que ayant perdu de vue le C++ depuis ... longtemps et surtout ne comprenant pas trop bien l'inter�t de son usage en environnement manag�) :

    - je ne comprends pas pourquoi tu instancies ta form avant d'�crire dans le TextBox.

    - si tu veux �crire depuis un thread secondaire, il faut que tu utilises le thread qui a instanci� la forme pour acc�der � un control quelconque.

    - pour cela, utiliser la m�thode Invoke sur la Form et pas sur le delegate. (tester pr�alablement via la propri�t� InvokeRequired)

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    3
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 3
    Par d�faut
    En effet je ne sais pas non plus pourquoi je cr�ait une nouvelle instance avant l'appel de ma fonction. �a m'apprendra � copier des exemples.
    J'ai donc cr�� une variable de type Projet::Form1 et pointant sur le thread principal contenant les contr�les.
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    static Projet::Form1 ^MainForm;
    et dans le code constructeur de la form :
    J'ai adapt� l'appel de mon d�l�gu� comme tu me l'as indiqu� :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    Ecrire ^ pointeur = gcnew Ecrire(Projet::Form1::MainForm, &Projet::Form1::EcrireTextBox);
    if(Projet::Form1::MainForm->InvokeRequired) 
    {
    	Projet::Form1::MainForm->Invoke(pointeur);		 
     
    }
    Et �a marche ! merci beaucoup!

    J'ai utilis� le C++ car les fonctions bas-niveau pour la liaison s�rie sont fournies par le constructeur du p�riph�rique en C++. Si tu vois une autre solution beaucoup plus simple, �a m'int�resse. (Sachant que le fabricant propose aussi son code en C# mais je ne connais pas du tout ce langage).

  4. #4
    Expert confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 507
    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 507
    Par d�faut
    STOP.
    Pas de variables globales d�guis�es.

    Si vous avez besoin d'acc�der � un objet unique depuis n'importe quel endroit de votre programme, cela s'appel un singleton et cela s'impl�mente avec le Design Pattern Singleton, pas avec un membre static non thread-safe, non AppDomain-Aware etc. .

    Citation Envoy� par Bluedeep Voir le message
    - je ne comprends pas pourquoi tu instancies ta form avant d'�crire dans le TextBox.


    Vous devez avoir la form instanci� pour avoir les contr�les qu'elle contient instanci�s. Il faut que l'objet contr�le soit instanci� pour pouvoir initialiser une de ses propri�t�s.

    Moi, je passerais tout simplement une r�f�rence de la form � la routine du thread (n�2) qu'elle utiliserait directement.



    Targus003, je pense que vous souffrez d'un syndrome extr�mement commun pour un programmeur C++ d�butant dans les applications multi-thread�s avec IHM, que j'appellerais le clivage Objet/Thread.

    La conception d'Objet en C++ n'est pas celle d'Objective-C ou de SmallTalk.
    Dans ces langages, chaque objet dispose de sa propre file de message et l'appel de m�thode correspond � l'envoie synchrone d'un message et de la r�cup�ration de sa r�ponse. Un seul thread a le droit de lire la file de message d'un objet. Il y a donc cloisonnement strict entre les autres threads et l'objet. L'objet n'est associ� qu'� un thread dans ces langages.
    (Je ne suis pas un sp�cialistes de ces langages, j'esp�re n'avoir pas dit trop de conneries )

    En C++, ce n'est pas du tout le cas. Un objet n'est pas "h�berg�" dans un thread. Tous les threads peuvent appeler les m�thodes de tous les objets. Le fait de d�clarer une m�thode dans la form ne garanti pas que celle-ci ne sera appel� que depuis le thread cr�ateur de la form.

    Pour les coupeurs de cheveux en quatre, on peut avoir recoure au STA de COM ou � de multiples AppDomain en .NET pour simuler le comportement "� la smallTalk" de l'h�bergement des objets dans des threads.
    C'est tr�s complexe et ne correspondra pas aux habitudes de conception des programmeurs C++ exp�riment�s.

    Pour ma part, j'essaye de conserver ces probl�matiques loin de mon code par l'utilisation du principe d'encapsulation de la POO.
    En termes clairs, c'est d'encapsuler les m�thodes qui sont "sensibles" au thread les appelants, dans une esp�ce de sas � thread.

    Le sas a, dans le cas d'une form, toujours la m�me t�te:

    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
     
    public: void méthode_SAS(void)
    {
            if(InvokeRequired)
            {
                    Invoke(méthode_sensible);
            }
            else
            {
                    méthode_sensible();
            }
    }
     
    private: void méthode_sensible(void)
    {
            ...
    }
    Et ne jamais appeler m�thode_sensible directement.

  5. #5
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 64
    Localisation : France

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par d�faut
    Citation Envoy� par bacelar Voir le message
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    - je ne comprends pas pourquoi tu instancies ta form avant d'écrire dans le TextBox.


    Vous devez avoir la form instanci� pour avoir les contr�les qu'elle contient instanci�s. Il faut que l'objet contr�le soit instanci� pour pouvoir initialiser une de ses propri�t�s.
    IL est �vident qu'il faisait une instanciation de sa form � l'int�rieur du code de celle-ci. Ce qui n'a aucun sens.

    Moi, je passerais tout simplement une r�f�rence de la form � la routine du thread (n�2) qu'elle utiliserait directement.
    Cela me semble �vident. Mais on a pas le code global, donc inf�rer sur les d�tails d'impl�mentation est d�licat.


    En C++, ce n'est pas du tout le cas. Un objet n'est pas "h�berg�" dans un thread. Tous les threads peuvent appeler les m�thodes de tous les objets. Le fait de d�clarer une m�thode dans la form ne garanti pas que celle-ci ne sera appel� que depuis le thread cr�ateur de la form.
    Ici la probl�matique n'est pas du tout C++, mais .Net.

    C'est tr�s complexe et ne correspondra pas aux habitudes de conception des programmeurs C++ exp�riment�s.
    Programmeurs qui founissent en g�n�ral des codes d�plorables dans les �nvironnements manag�s ....

  6. #6
    Expert confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 507
    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 507
    Par d�faut
    Citation Envoy� par Bluedeep Voir le message
    Ici la probl�matique n'est pas du tout C++, mais .Net.


    Un objet est accessible par n'importe quel thread.
    Sur cet aspect, .NET, C++/CLI et C++ ont tous le m�me comportement.


    Exemple C++ non .NET, les MFC, o� il n'y a pas un gramme de .NET, utilisent les des SendMessage et du hooking de fen�tre pour palier � ces "limitations".

    O�, dans la norme C++, est indiqu� que les acc�s aux objets sont circonscrit � un thread "cr�ateur"?

  7. #7
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 64
    Localisation : France

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par d�faut
    Citation Envoy� par bacelar Voir le message
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    Ici la problèmatique n'est pas du tout C++, mais .Net.


    Un objet est accessible par n'importe quel thread.
    C'est ici que vous prof�rez une erreur grossi�re, visiblement par m�connaissance de l'environnement .Net (qui est celui utilis� par le posteur initial).

    Dans l'environnement .Net, les propri�t�s (sauf 'InvokeRequired') des instances d'objets h�rit�s de Control ne sont manipulables que par le thread qui les a instanci�s.

    Comme vous ne disposez pas forc�ment d'une r�f�rence � ce thread, tous ces objets exposent une m�thode 'Invoke' permettant l'ex�cution d'un delegate dans le contexte du thread ayant cr�� l'instance de l'objet en question.

    Sur cet aspect, .NET, C++/CLI et C++ ont tous le m�me comportement.
    Je ne vois pas le rapport entre le langage et le framework.

    Exemple C++ non .NET, les MFC, o� il n'y a pas un gramme de .NET, utilisent les des SendMessage et du hooking de fen�tre pour palier � ces "limitations".
    Oui, c'est la b-a-ba de la programmation windows "native".

    O�, dans la norme C++, est indiqu� que les acc�s aux objets sont circonscrit � un thread "cr�ateur"?
    Encore une fois, le langage utilis� n'a strictement rien � voir avec la probl�matique.

  8. #8
    Expert confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 507
    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 507
    Par d�faut
    Pour le probl�me de Targus003 ; Bluedeep es-tu d'accord que mon code est convenable ?

    C'est qu'apr�s, on va avoir droit � une discutions de "casse-couilles" qui n'aidera pas � r�soudre correctement le probl�me de Targus003.

    Citation Envoy� par Bluedeep Voir le message
    C'est ici que vous prof�rez une erreur grossi�re, visiblement par m�connaissance de l'environnement .Net (qui est celui utilis� par le posteur initial).

    Dans l'environnement .Net, les propri�t�s (sauf 'InvokeRequired') des instances d'objets h�rit�s de Control ne sont manipulables que par le thread qui les a instanci�s.
    Cela n'a strictement rien avoir avec .NET et vu votre connaissance du code natif sous Windows, vous le savez tr�s bien.
    Utilisez Reflector pour voir l'impl�mentation de la propri�t� Text et vous tomberez sur des SetWindowText de l'API Win32 notablement dangereuse pour cause de deadlock.
    Cette limitation vient directement des contr�les Windows, comme en code natif.
    C'est �trange, c'est li� � .NET mais en code natif, C++ ou pas, on a le m�me probl�me. Bizarre non ?

    Il faut juste que l'utilisateur comprenne que l'objet n'est pas isol� dans un thread comme en smallTalk mais qu'il est accessible par tous les threads. Et cela est vrai en C++ mais pas dans des langages .NET comme F#, je crois.

  9. #9
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 64
    Localisation : France

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par d�faut
    Citation Envoy� par bacelar Voir le message
    Pour le probl�me de Targus003 ; Bluedeep es-tu d'accord que mon code est convenable ?
    Enti�rement d'accord, mais j'ai l'impression qu'on l'embrouille quelque peu

    Il faut juste que l'utilisateur comprenne que l'objet n'est pas isol� dans un thread comme en smallTalk mais qu'il est accessible par tous les threads. Et cela est vrai en C++ mais pas dans des langages .NET comme F#, je crois.
    Je ne connais pas du tout SmallTalk, m�me approximativement, donc ne ferais pas de comparaison avec.

    Je n'ai par ailleurs jamais dit que l'objet �tait isol� dans un thread.

    Concernant F# je ne l'ai pas regard� encore d'assez pr�s pour �tre affirmatif.

    Concernant les autres langages .Net (VB.Net et C#), il n'y a aucune limitation � l'acc�s entre thread des objets, du point de vue de la visibilit�; il y peu y avoir en revanche des limitations de manipulations inter-thread, li�s � l'impl�mentation. (valable en C++ aussi).

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    3
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 3
    Par d�faut
    Merci pour ces pr�cisions. J'avoue �tre un peu perdu dans tout �a mais l'essentiel est que mon petit bout de code marche et mon projet est d�bloqu�. Un �lectronicien se contente de peu.

    Je suis toujours preneur de conseils pour la r�alisation rapide d'interface graphique communicant avec un port s�rie (sujet r�current dans mes projets). J'ai d�j� travaill� avec les MFC, maintenant les Windows Form et je trouve la programmation tr�s fastidieuse pour r�aliser des fonctions assez basiques.

  11. #11
    Expert confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 507
    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 507
    Par d�faut
    Je pense que le caract�re fastidieux est un corolaire d'utilisation de code mal con�u.

    Exemple, notre cas de figure :

    Votre Code ~
    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
     
    ...
    delegate void Ecrire(void);
    ...
    static Projet::Form1 ^MainForm;
     
    public ref class Projet::Form1 : ...
    {
    ...
       MainForm=this;
    ...
    public: void EcrireTextBox(void)
    		{
    			textBox1->AppendText("OK");
    		}
    ...
    }
    ...
    TITI::méthode1
    {
    ...
           Ecrire ^ pointeur = gcnew Ecrire(Projet::Form1::MainForm, &Projet::Form1::EcrireTextBox);
          if(Projet::Form1::MainForm->InvokeRequired) 
          {
    	Projet::Form1::MainForm->Invoke(pointeur);		 
     
          }
    ...
    }
    ...
    TATA::méthode2
    {
    ...
           Ecrire ^ pointeur = gcnew Ecrire(Projet::Form1::MainForm, &Projet::Form1::EcrireTextBox);
          if(Projet::Form1::MainForm->InvokeRequired) 
          {
    	Projet::Form1::MainForm->Invoke(pointeur);		 
     
          }
    ...
    }
    ...
    TOTO::méthode3
    {
    ...
           Ecrire ^ pointeur = gcnew Ecrire(Projet::Form1::MainForm, &Projet::Form1::EcrireTextBox);
          if(Projet::Form1::MainForm->InvokeRequired) 
          {
    	Projet::Form1::MainForm->Invoke(pointeur);		 
     
          }
    ...
    }
    Mon code
    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
     
     
    public ref class Projet::Form1 : ...
    {
    ...
       public: void SetOK(void)
       {
            if(InvokeRequired)
            {
    	Invoke(_EcrireTextBoxOK());
            }
            else
            {
    	_EcrireTextBoxOK();
            }
       }
     
       private: void _EcrireTextBoxOK(void)
       {
            textBox1->AppendText("OK");
       }
    ...
    }
     
     
    TITI::méthode1
    {
    ...
       myForm1.SetOK();
    ...
    }
    ...
    TATA::méthode2
    {
    ...
       myForm1.SetOK();
    ...
    }
    ...
    TOTO::méthode3
    {
    ...
       myForm1.SetOK();
    ...
    }

  12. #12
    Membre �clair�
    Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2008
    Messages
    289
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : F�vrier 2008
    Messages : 289
    Par d�faut
    bonjour,
    je reprend le sujet car je suis dans la m�me config que targus003 avec un thread2 cr�� par thread1 et qui veut afficher ce qu'il re�oit dans une textBox port�e par thread1.
    J'ai donc �crit ceci en m'inspirant de ce que vous avez propos� et d'un peu de msdn:
    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
     
    fichier form1.h:
    ----------------
    private:
        delegate void Ecrire();	//la "fonction" déléguée
        Ecrire^ myDelegate;	//une référence pointant sur la fonction déléguée
     
    Form1()
    {
        myDelegate = gcnew Ecrire(this, &Form1::writeTextBox);
    }
     
    private: System::Void btnStart_Click(System::Object^ sender, System::EventArgs^ e) {
        Thread^ InstanceCaller = gcnew Thread(gcnew ThreadStart(this, &Form1::ThreadFunction));
        // Start the thread.
        InstanceCaller->Start();
    }
     
    private: void ThreadFunction() {
        //Instancier un objet de la classe threadClass en lui passant la Form1
        threadClass^ myThreadClassObject = gcnew threadClass(this);
        myThreadClassObject->Run();
    }
     
    Fichier threadClass.cpp
    -----------------------
    threadClass::threadClass(Form^ f)
    {
        mainForm = f;    //recopie de la Form1 dans l'attribut Form^ mainForm
    }
     
    void threadClass::Run()
    {
        mainForm->Invoke(mainForm->myDelegate);
    }
    J'ai toujours l'erreur
    threadClass.cpp(32): error C2039: 'myDelegate'*: n'est pas membre de 'System::Windows::Forms::Form'
    comme si mainForm ne "pointait" pas vraiment sur Form1

    Merci de rabaisser mon niveau d'incomp�tence.

  13. #13
    Expert confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 507
    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 507
    Par d�faut
    Je n'ai pas tout le code, mais je pense que vous avez d�clar� le champ "mainForm" de la classe threadClass comme un objet de type "Form" et non un objet de type Form1
    (attention les noms des classes devraient commencer par une majuscule )

    Changez la d�claration de ce champ et la signature de "threadClass::threadClass(Form^ f)"" en "threadClass::threadClass(Form1^ f)"

    Le compilateur vous foutra la paix.

  14. #14
    Membre �clair�
    Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2008
    Messages
    289
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : F�vrier 2008
    Messages : 289
    Par d�faut
    bonjour
    je poste mon code expurg� de ce qui ne concerne pas le probl�me.
    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
     
    Fichier form1.h:
    ----------------
    namespace tstThread {
        public ref class Form1 : public System::Windows::Forms::Form
        {
            public:
                Form1(void)
    	    {
    		myDelegate = gcnew Ecrire(this, &Form1::writeTextBox);
    	    }
     
            private:
                delegate void Ecrire();	//la "fonction" déléguée
    	Ecrire^ myDelegate;	//une référence sur la fonction déléguée
     
    	//Gestion du bouton Exit
    	private: System::Void btnExit_Click(System::Object^ sender, System::EventArgs^ e) {
    	    Application::Exit();
    		}
     
    	//Gestion du bouton Start
    	private: System::Void btnStart_Click(System::Object^ sender, System::EventArgs^ e) {
    	    threadClass^ myThread = gcnew threadClass(this);    //passe une référence sur Form1
    	    Thread^ InstanceCaller = gcnew Thread(gcnew ThreadStart(myThread, &threadClass::Run));
    	    // Start the thread.
    	    InstanceCaller->Start();
    	}
     
    	private: void ThreadFunction() {
    	    System::Windows::Forms::MessageBox::Show("ThreadFunction");
    	    threadClass^ myThreadClassObject = gcnew threadClass(this);
    	    myThreadClassObject->Run();
    	}
     
    	/* méthode exécutée par le délégué */
    	public: void writeTextBox() {
    	    this->textBox1->Text = "Hello";
    	}
        };
    }
     
    Fichier threadClass.h:
    ----------------------
    ref class threadClass
    {
        private:
            System::Windows::Forms::Form^ mainForm;
     
        public:
            threadClass(Form^);
            void Run();
    };
     
    Fichier threadClass.cpp:
    ------------------------
    #include "threadClass.h"
     
    threadClass::threadClass(Form^ f)
    {
        mainForm = f;
    }
     
    void threadClass::Run()
    {	
        if(mainForm->InvokeRequired)
            System::Windows::Forms::MessageBox::Show("threadClass::InvokeRequired = true");
        else System::Windows::Forms::MessageBox::Show("threadClass::InvokeRequired = false");
     
        mainForm->Invoke(mainForm->myDelegate);
    }
    Utiliser Form1 au lieu de Form comme sugg�r� ne compile pas car Form1 n'est pas connu au niveau de threadClass. Il me manque peut-�tre une d�claration quelque part.

    La m�thode Run affiche true (si je commente l'appel � la propri�t�
    InvokeRequired) sinon le compilateur r�pond toujours:
    error C2039: 'myDelegate'*: n'est pas membre de 'System::Windows::Forms::Form'
    Le souci ne viendrait-il pas de l'instruction: mainForm = f; ? qui fait que mainForm est bien de type Form^ mais ne "pointe" pas vraiment sur Form1 et donc ne conna�t pas l'attribut myDelegate. Une mauvaise affectation en quelque sorte.

    Merci.

  15. #15
    Expert confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 507
    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 507
    Par d�faut
    Vos remarques/explications semble montrer que vous n'�tes pas tr�s � l�aise avec les langages orient� objet � typage statique, comme C++, C++/CLI, JAVA ou encore C#.

    Peut-�tre avez-vous l'habitude de langage � typage dynamique comme python ou PHP ?

    En tout cas en C++/CLI, le typage est statique, c'est � la compilation que le type des variables est indiqu� ou inf�r�. C'est le compilateur qui doit v�rifier la concordance des types et soit faire les conversions implicites soit indiquer les erreurs de typage (erreur "statique").

    Donc c'est normal que le compilateur hurle quand il voit :
    Si mainForm est d�clar� avec :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    System::Windows::Forms::Form^ mainForm;
    Le compilateur connait l'ensemble des membre de "System::Windows::Forms::Form" et sait, � la compilation, qu'il ne contient pas de membre "myDelegate" et refuse d'aller plus loin.
    M�me si, � l'ex�cution, l'objet fourni au constructeur de "threadClass" contiendrait ce membre, le compilateur n'en a cure. il fait une v�rification statique et Form ne contient pas de "myDelegate".

    Si le champ "mainForm" de la classe 'threadClass" n'est plus une "System::Windows::Forms::Form" mais une "...::Form1", il n'y a plus ce probl�me car le compilateur c'est qu'un objet de type ""...::Form1" a un membre "myDelegate".
    Le seul hic, c'est que le compilateur vous indiquera que vous ne pouvez pas acc�der � un membre priv� d'une classe depuis le code d'une autre. Il suffit de d�clarer "myDelegate" comme public et non comme private.

    Ceci est une d�claration d'un type de delegate, pas d'un delegate.
    OK ?

    Le type du delegate doit aussi �tre connu par le code appelant, donc soit vous faite en sorte que la d�claration du type soit public, soit, et je vous le conseil, d'utiliser des types de delegate d�j� d�finis dans le Framework comme la classe Action (http://msdn.microsoft.com/en-us/libr...em.action.aspx).

    Donc le probl�me fondamental est pourquoi votre code de la classe "threadClass" ne connais pas le type "...::Form1".
    Normalement, un simple sous le #pragme once devrait suffire.

    Attention, par d�faut, la classe Form1 est d�clar� dans un namespace dont le nom est en lien avec le nom du projet. il faut donc soit utiliser un "using namespace ..." avant la classe threadClass, soit pr�fixer Form1 par ce namespace lors de la d�finition du membre de type Form1.

    Ceci est un POC.
    Dans un projet, je pense que votre classe threadClass doit pouvoir �tre utilis� avec plusieurs types de Form. Cela est facilement r�alisable :
    - soit en sp�cifiant une interface d�clarant le delegate et toutes les classes de Form devraient l'impl�menter. threadClass pendrait un objet de "type" cette interface.
    - soit en sp�cifiant une classe d�rivant de Form d�clarant le delegate et toutes les classes de Form devraient en h�riter. threadClass pendrait un objet de "type" cette classe.

  16. #16
    Membre �clair�
    Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2008
    Messages
    289
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : D�veloppeur informatique

    Informations forums :
    Inscription : F�vrier 2008
    Messages : 289
    Par d�faut
    Merci pour vos pr�cieuses explications.
    Je viens du C et j'ai une connaissance toute livresque du C++ et de l'objet en g�n�ral. Je n'aurais peut �tre pas d� commencer par Visual et son CLI/C++.

    J'ai modifi� mon code comme ceci:
    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
     
    Fichier threadClass.h:
    ----------------------
    #pragma once
     
    #include "Form1.h"
    using namespace tstThread;
     
    ref class threadClass
    {
        private:
    	Form1^ mainForm;    //mainForm est un handle sur Form1
     
        public:
    	threadClass(Form1^);//le constructeur reçoit un handle sur Form1
    };
     
    Fichier threadClass.cpp:
    ------------------------
    #include "StdAfx.h"
    #include "threadClass.h"
     
    using namespace System::Windows::Forms;
    using namespace System::Threading;
    using namespace tstThread;
     
    threadClass::threadClass(Form1^ f)
    {
        mainForm = f;
    }
     
    Fichier Form1.h:
    ----------------
    #pragma once
     
    #include "threadClass.h"
     
    namespace tstThread {
     
        public ref class Form1 : public System::Windows::Forms::Form
        {
    	..... code de la classe .....
     
    	private: System::Void btnStart_Click(System::Object^ sender, System::EventArgs^ e) {
    	    threadClass^ myThread = gcnew threadClass(this);    //this est un handle sur Form1
    	}
        }
    };
    Du coup, le #include "Form1.h" dans le fichier threadClass.h g�n�re des dizaines de lignes d'erreurs jusque dans le fichier tstThread.cpp et le compilateur me dit que tstThread n'est pas un espace de noms connu.
    Est-ce qu'il n'y aurait pas une sorte de pb d'inclusions multiples? (dont le #pragma once aurait d� nous pr�munir).

    Interface et classe Action au menu des vacances de P�ques...

Discussions similaires

  1. Thread et TextBox
    Par archer dans le forum C#
    R�ponses: 8
    Dernier message: 20/05/2008, 00h14
  2. R�ponses: 5
    Dernier message: 19/05/2008, 10h31
  3. Controler des textBox dans des thread
    Par ramaro dans le forum Windows Forms
    R�ponses: 5
    Dernier message: 25/04/2008, 14h21
  4. Textbox et Thread
    Par migutz dans le forum VB.NET
    R�ponses: 1
    Dernier message: 22/04/2008, 12h46
  5. [vc++ 2005] acceder a un textbox a partir d un thread
    Par jerome86600 dans le forum VC++ .NET
    R�ponses: 9
    Dernier message: 12/07/2006, 13h10

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