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 Forms Discussion :

[C#]Cross-thread operation not valid


Sujet :

Windows Forms

  1. #1
    hrp
    hrp est déconnecté
    Membre à l'essai
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut [C#]Cross-thread operation not valid
    Bonjour,

    j'aimerai créer une class possédant des événements. Cette class lance également un thread qui va déclancher l'événement. Dans le code où est instancier un objet de cette class, j'abonne une méthode à l'événement. Dans cette méthode je modifie la propriété text d'un objet RichTextBox. Lorsque l'événement survient la méthode abonnée à l'événement s'éxécute bien mais une exception survient au momment de la modification du RichTextBox. Ceci survient car l'appel de cette méthode provient d'un autre thread que celui où est instancié l'objet RichTextBox. Une solution est d'utiliser la méthode BeginInvoke et de lui passer une méthode delegate.
    Cependant existe-t-il une autre solution permettant d'éviter l'utilisation de la méthode BeginInvoke?
    En fait j'aimerai que l'utilisateur de la class générant les événements n'ai pas à ce soucier des problèmes de "Cross-thread operation not valid"

    Merci pour votre support

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    238
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 238
    Points : 269
    Points
    269
    Par défaut
    Salut,
    D'un point de vu sécurité il est interdit à un Thread de pouvoir modifier un composant graphique qu'il n'a pas crée lui-même. Ca permet d'éviter des conflit d'accès aux ressources.
    Mais il y a moyen de supprimer cette sécurité :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CheckForIllegalCrossThreadCalls = false;
    pose cette ligne de code avant de faire le start de ton premier Thread et ca devrait marché sans pb !

    Bonne chance
    « L’erreur est humaine, mais un vrai désastre nécessite un ordinateur »

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    Salut,
    J'ai été face au même problème que toi.
    La solution que j'ai mis en place pour ce problème, c'est de mettre toutes les modifs que j'avais a faire sur mes objets graphiques dans la classe de mon ihm.
    Ensuite dans cette méthode, tu dois mettre en place le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    delegate void dMaMethode();
    public void maMethode()
    {
       if (this.InvokeRequired)
       {
           dMaMethode d = new dMaMethode(maMethode);
           this.Invoke(d);
       }
       else
       {
           //ton traitement
       }
    }
    Tu appelera cette methode dans la méthode qui reçoit l'evenement. Et là, normalement ya plus aucun problème .

    J'espere que j'ai été clair et que ça pourra t'aider...

  4. #4
    Membre actif
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    238
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 238
    Points : 269
    Points
    269
    Par défaut
    Ma réponse fonctionne, tu devrais l'essayer yagosacquet, je pense que c'es plus simple que ta proposition.
    « L’erreur est humaine, mais un vrai désastre nécessite un ordinateur »

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 5
    Points : 5
    Points
    5
    Par défaut
    C'est trop tard, j'ai déjà mis en place ma méthode partout (long, très long...)
    La méthode que je propose est pas si compliqué que ça (c'est celle qui est proposé sur msdn pour résoudre les problèmes de cross threading).
    Bon c'est sur ta méthode est beaucoup plus simple .

  6. #6
    hrp
    hrp est déconnecté
    Membre à l'essai
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut Cross-thread operation not valid
    La méthode que propose yagosacquet est celle que j'utilise aussi, la méthode de Biloutor ne me plaît pas car il faut prendre en compte la synchronisation entre les le thread générant l'événement et le thread de l'IHM.

    Bref, mon problème n'est cependant pas complètement résolu. En fait avec la méthode de yagosacquet ça fonctionne très bien mais l'utilisateur de la classe générant l'événement doit savoir qu'il doit utiliser la méthode Invoke().
    Moi j'aimerai faire en sort qu'il n'a pas besoin de savoir tout ça.
    Lorsqu'on utilise un composant System::Windows::Forms::Button, il n'est pas nécéssaire d'utiliser la méthode Invoke() dans la methode System::Void buttonXY_Click(System::Object^ sender, System::EventArgs^ e). Comment est solutionné l'appel de cette événnement OnClick dans las classe System::Windows::Forms::Button?
    J'aimerai aboutir au même résultat...
    Est-ce possible?
    Merci
    hrp

  7. #7
    Membre éclairé
    Avatar de shwin
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    568
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Novembre 2003
    Messages : 568
    Points : 777
    Points
    777
    Par défaut
    Citation Envoyé par Biloutor
    Salut,
    D'un point de vu sécurité il est interdit à un Thread de pouvoir modifier un composant graphique qu'il n'a pas crée lui-même. Ca permet d'éviter des conflit d'accès aux ressources.
    Mais il y a moyen de supprimer cette sécurité :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CheckForIllegalCrossThreadCalls = false;
    pose cette ligne de code avant de faire le start de ton premier Thread et ca devrait marché sans pb !

    Bonne chance
    Ta méthode est totalement à déconseiller. Si tu utilise cette méthode, aussi bien de toutes mettre tes class static et mettre tout les membre public. C'est sensiblement la meme chose.

    Si tu veux acceder a un composant, utilise un invoke pour changer de thread.

    Aussi, si tu veux voir comment fonctionne le onclick d'un bouton, je te conseille de downloader un reflector .
    Remoting Context Matters
    Everything in this chapter is 100 percent undocumented. Reliance on these techniques is not supported by either Microsoft, the publisher, or the author of this book. Use at you own risk! If your computer won't work afterwards, your toaster blows up or your car doesn't start, I assume no liability whatsoever: You're now about to enter the uncharted territories of .NET and you do so on your own risk. I can only provide some guidance

  8. #8
    Rédacteur
    Avatar de dev01
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 451
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 451
    Points : 6 017
    Points
    6 017
    Par défaut
    Citation Envoyé par shwin
    Ta méthode est totalement à déconseiller.
    +1. Si les opérations cross thread sont interdites c'est qu'il y a une (des) raisons pour ça. Supprimer les messages d'erreur n'est pas synonime de résolution de problème. C'est comme de tuer le messager pour pas avoir les mauvaises nouvelles ...
    - MVP C#
    -Tout problème a une solution, le vrai problème est de trouver la solution .....
    - Linux & mono : l'avenir

  9. #9
    Membre éclairé
    Avatar de shwin
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    568
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Novembre 2003
    Messages : 568
    Points : 777
    Points
    777
    Par défaut
    Citation Envoyé par dev01
    +1. Si les opérations cross thread sont interdites c'est qu'il y a une (des) raisons pour ça. Supprimer les messages d'erreur n'est pas synonime de résolution de problème. C'est comme de tuer le messager pour pas avoir les mauvaises nouvelles ...
    Belle comparaison
    Remoting Context Matters
    Everything in this chapter is 100 percent undocumented. Reliance on these techniques is not supported by either Microsoft, the publisher, or the author of this book. Use at you own risk! If your computer won't work afterwards, your toaster blows up or your car doesn't start, I assume no liability whatsoever: You're now about to enter the uncharted territories of .NET and you do so on your own risk. I can only provide some guidance

  10. #10
    hrp
    hrp est déconnecté
    Membre à l'essai
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut Cross-thread operation not valid
    Merci à shwin,
    je vais analyser un peu avec le reflector. Cette outil est géniale! merci beaucoup pour votre aide.
    @+
    hrp

  11. #11
    Membre actif
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    238
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 238
    Points : 269
    Points
    269
    Par défaut
    j'aime pas les postiers !
    « L’erreur est humaine, mais un vrai désastre nécessite un ordinateur »

  12. #12
    En attente de confirmation mail
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    1 249
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 249
    Points : 314
    Points
    314
    Par défaut
    bonjour,

    j'ai le même type de probleme mais je suis en VB : est-ce que vous pouvez me donner un exemple de code en VB utilisant la command Invoke, je n'arrive pas à l'utiliser....

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Bonjour,

    je suis comfronté au meme probleme et je ne parviens pas à trouver la solution.
    De plus, pas moyens de telecharger ce fameux 'Reflector'.

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Citation Envoyé par Gogor
    Bonjour,

    je suis comfronté au meme probleme et je ne parviens pas à trouver la solution.
    De plus, pas moyens de telecharger ce fameux 'Reflector'.
    Salut,

    tu n'arrives pas à resoudre ton probleme meme avec [Control].Invoke ? La solution qu'a proposé Yagosacquet est pourtant parfaitement fonctionnelle.

    @ Yagosacquet:
    pour eviter d'avoir à créer un délégué pour une methode de type void MaMethode(void), on peut utiliser le delegué standard MethodInvoker dans le namespace System.Windows.Forms.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void MyMethod()
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(new MethodInvoker(MyMethod));
                    }
                    else
                    {
                        //Traitement
                    }
                }
    Ce n'est pas le trick du siecle mais ca evite de declarer un nouveau delegué pour une methode sans retour ni parametres. =)

  15. #15
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    En fait, le probleme vient du fait que j'aimerai que le probleme du cross-Threading soit résolu du coté de la classe ou se trouve le thread.

    Moi, j'implemente une classe (avec le thread et les events...)

    pour un utilisateur qui doit pouvoir exécuter sa méthode (au déclenchement de mon event) sans devoir utiliser un Invoke.

    Exactement comme le décrit hrp plus haut

    La méthode que propose yagosacquet est celle que j'utilise aussi, la méthode de Biloutor ne me plaît pas car il faut prendre en compte la synchronisation entre les le thread générant l'événement et le thread de l'IHM.

    Bref, mon problème n'est cependant pas complètement résolu. En fait avec la méthode de yagosacquet ça fonctionne très bien mais l'utilisateur de la classe générant l'événement doit savoir qu'il doit utiliser la méthode Invoke().
    Moi j'aimerai faire en sort qu'il n'a pas besoin de savoir tout ça.
    Lorsqu'on utilise un composant System::Windows::Forms::Button, il n'est pas nécéssaire d'utiliser la méthode Invoke() dans la methode System::Void buttonXY_Click(System::Object^ sender, System::EventArgs^ e). Comment est solutionné l'appel de cette événnement OnClick dans las classe System::Windows::Forms::Button?
    J'aimerai aboutir au même résultat...
    Est-ce possible?
    Merci
    hrp

  16. #16
    hrp
    hrp est déconnecté
    Membre à l'essai
    Inscrit en
    Janvier 2005
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 10
    Points : 10
    Points
    10
    Par défaut une solution cross-Threading sans Invoke
    Bonjour Gogor,

    La méthode de Yagosacquet est celle que l'on retrouve le plus souvent dans les forum et dans les tutoriels. J'ai finalement trouvé une autre méthode tout aussi efficace il me semble et qui pourrait convenir.
    On peut trouver cette technique ici: http://msdn2.microsoft.com/fr-fr/lib...67(VS.80).aspx

    Une version un peu simplifier de tout ça (en c++/cli):
    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
     
    using namespace System::ComponentModel;
    using namespace System::Threading;
     
    ref class MaClass
    {
    public:
    	MaClass()
    	{
    		this->isThreadSafe = false;
    		//lancement de mon thread
    		this->monThread= gcnew Thread(gcnew ThreadStart(this, &MaClass::MaThreadProc));
    		this->monThread->Start();
    	}
    	MaClass(Object^ SynchronizingObject)
    	{
    		this->asyncOp = AsyncOperationManager::CreateOperation(SynchronizingObject);	//initialisation de mon opération asynchrone
    		this->onInitialized = gcnew SendOrPostCallback(this, &MaClass::ReportInitialized);	//initialisation du delegate
    		this->isThreadSafe = true;
    		//lancement de mon thread
    		this->monThread= gcnew Thread(gcnew ThreadStart(this, &MaClass::MaThreadProc));
    		this->monThread->Start();
    	}
     
    private:
    	AsyncOperation^ asyncOp;
    	Boolean isThreadSafe;
    	Thread^ monThread;
     
    public:
    	event EventHandler^ Initialized;	//mon event
     
    protected:
    	SendOrPostCallback^ onInitialized;	//mon delegate
     
    protected:
    	void ReportInitialized(Object^ obj)
    	{
    		try
    		{
    			this->Initialized(this, EventArgs::Empty);
    		}
    		catch(Exception^ ex)
    		{
    			ex->Message;
    		}
    	}
     
    private:
    	void MaThreadProc(void)
    	{
    		for(int i = 0; i < 10; i++)
    		{
    			Thread::Sleep(1000);	//j'initialise pendant 10s, c'est long...
    		}
    		//génération de mon event
    		if(this->isThreadSafe)
    		{
    			this->asyncOp->Post(this->onInitialized, EventArgs::Empty);
    		}
    		else
    		{
    			this->ReportInitialized(EventArgs::Empty);
    		}
    	}
    };
    pour l'utilisation de cette class il suffit d'instancier un object de cette class et d'abonner une fonction à son event Initialized. Pour être Thread-safe il faut utiliser le constructeur avec parametre et passer this comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    MaClass^ maClass = gcnew MaClass(this);
    maClass->Initialized += gcnew EventHanlder(this, &maClass_Initialized);
    et dans la fonction maClass_Initialized on est thread-safe c'est à dire dans le bon thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void maClass_Initialized(Object^ sender, EventArgs^ e)
    {
    	//update d'un control...
    	this->monTextBox->Text = "maClass initialisée!";
    }
    au passage, tu trouveras Reflector ici:
    http://www.aisto.com/roeder/DotNet/

    j'espère ne pas avoir fait trop de faute dans l'exemple ci-dessus...

    PS: peut-être qu'il existe encore une autre technique avec l'interface ISynchronizeInvoke. J'ai pas encore eu le temps d'anaylser cette interface mais elle semble être conçue pour ça également. J'ai remarqué que le composant EventLog de System:iagnostics utilise cette interface.

    @++
    hrp

  17. #17
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2007
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Génial, je te remercie.

    Cela me fait progresser à pas de Géants.

    Ps: j'ai passé 1/2H à comprendre que le formulaire d'enregistrement sur : http://www.aisto.com/roeder/DotNet/
    demandait un nom en deux partie pour accepter la saisie

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Citation Envoyé par hrp
    PS: peut-être qu'il existe encore une autre technique avec l'interface ISynchronizeInvoke. J'ai pas encore eu le temps d'anaylser cette interface mais elle semble être conçue pour ça également. J'ai remarqué que le composant EventLog de System:iagnostics utilise cette interface.
    Bonjour,

    pour l'interface ISynchronizeInvoke, si tu decides de l'utiliser, cette source te donnera une idée d'une implementation de cette interface permettant de créer un thread et de poster des taches à ce thread par l'intermediaire d'Invoke(), BeginInvoke etc ...

    Bon courage. =)

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

Discussions similaires

  1. Thread : Operation inter-threads non valide
    Par conan76 dans le forum VB.NET
    Réponses: 13
    Dernier message: 14/05/2015, 22h50
  2. Cross-thread operation not valid && serialport
    Par vince_lille dans le forum Windows Forms
    Réponses: 4
    Dernier message: 20/04/2007, 11h57
  3. [VB.NET]Erreur "invalid cross-thread operation"
    Par NicolasJolet dans le forum Windows Forms
    Réponses: 6
    Dernier message: 05/04/2006, 12h38
  4. xhtml ->xml xsl:attribute name+not valid
    Par yos dans le forum XSL/XSLT/XPATH
    Réponses: 9
    Dernier message: 14/06/2005, 07h27
  5. Réponses: 2
    Dernier message: 19/04/2005, 15h29

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