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

Communications inter threads


Sujet :

C#

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut Communications inter threads
    Bonjour, je souhaiterai réaliser un affichage rafraichi toutes les 100ms.
    J'ai dans une classe l'ensemble du code d'affichage et dans l'autre les méthodes de traitements le tout s'articule ainsi

    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
     
    public partial class DiagnosticAffichage : UserControl
        {
            private System.Timers.Timer temps;
            private Diagnostic diagnostic;
     
            public DiagnosticAffichage()
            {
                InitializeComponent();
                diagnostic = new Diagnostic();
                TimerAction();
            }
     
            public void TimerAction()
            {
                temps = new System.Timers.Timer();
                temps.Interval = 200;
                temps.Elapsed += new ElapsedEventHandler(AppelAffichage);
                temps.Enabled = true;
                temps.Start();
            }
     
            public void AppelAffichage(object source, ElapsedEventArgs e)
            {
                Affichage();
            }
     
            public void Affichage()
            {
                this.ramLibre.Text = diagnostic.getMemoire();
                this.processeurPourcentage.Text = diagnostic.getProcesseur();
                this.disqueLibre.Text = diagnostic.getDisque();
                this.kbytesSec.Text = diagnostic.getReseau();
            }
        }
    J'ai l'erreur suivante qui apparaît :

    Opération inter-threads non valide : le contrôle 'ramLibre' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Je regarde mais j'ai du mal à trouver quelque chose de compréhensible pour savoir comment dans mon cas je dois géré cette communication inter-thread.
    Merci d'avance.

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    Salut,

    Le problème ne provient probablement pas du bout de code que tu nous montre. Est-ce que tu manipules ton objet "ramLibre" à partir d'un autre endroit dans ton code ?

    Je pense que tu dois le faire en passant directement ton objet ramLibre, or celui-ci s'éxecute déja sur un thread.
    Si tu as besoin de manipuler cet objet depuis l'exterieur de ta form, tu va devoir créer un event.

    Tu déclare ton event sur ta form.
    Ta fonction qui manipule "ramLibre" sera, de préférence, également sur ta form, afin qu'elle connaisse son éxistence.
    Et toi, de l'éxterieur, tu n'a plus qu'a déclenché cet event, en lui passant les paramètre dont tu as besoin.


    Je crois que ceci devrait résoudre ton problème.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    ramLibre est un label qui fait partie de la classe DiagnosticAffichage qui est un UserControl.

    DiagnosticAffichage est appellé dans une classe Fenetre qui est mon windows.form principal.

    Les méthodes getMemoire(), getProcesseur() sont des méthodes implémentés dans la classe Diagnostic mais cette classe est un membres de DiagnosticAffichage donc ca m'étonnai aussi qu'on me parle de thread.

    Le problème qui se pose pour ramLibre se posera également pour les 3 instructions suivantes.

    C'est la première fois que j'appréhende les Threads j'imagine que doit faire communiquer le thread de mon windows.form avec ma classe DiagnosticAffichage. Ai je raison ou je fait fausse route ? Et comment faut il s'y prendre ?

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Par défaut
    Le problème c'est que tu ne peux pas modifier un contrôle à partir d'un autre thread que celui de l'IHM. Pour renvoyer le traitement vers le thread de l'IHM il faut appeler les fonctions Control.Invoke() ou Control.BeginInvoke()

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    Ok je regarde depuis un long moment comment m'en servir donc si j'ai bien compris.

    Dans mon windows.form je déclare en variable un Thread et puis je défini ce thread de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    myThread = new Thread(new ThreadStart(fonctionThread));
    myThread.Start();
    dans fonctionThread on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    private void fonctionThread()
    {
          diagnostic = new DiagnosticAffichage(this);
          this.layout.Controls.Add(diagnostic);
          diagnostic.Run();
    }
    et enfin dans ma classe DiagnosticAffichage
    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
     
    public DiagnosticAffichage(Fenetre fenetre)
            {
                InitializeComponent();
                diagnostic = new Diagnostic();
                this.fenetre = fenetre;
            }
     
            public void Run()
            {
                temps = new System.Timers.Timer();
                temps.Interval = 200;
                temps.Elapsed += new ElapsedEventHandler(AppelAffichage);
                temps.Enabled = true;
                temps.Start();
            }
     
            public void AppelAffichage(object source, ElapsedEventArgs e)
            {
                this.ramLibre.Text = "12";
            }
     
            public void Affichage()
            {
     
                this.ramLibre.Text = diagnostic.getMemoire();
                this.processeurPourcentage.Text = diagnostic.getProcesseur();
                this.disqueLibre.Text = diagnostic.getDisque();
                this.kbytesSec.Text = diagnostic.getReseau();
            }
    Ce que je ne comprends pas c'est à quel moment j'appelle Control.Invoke et comment ?

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Par défaut
    Je pense que le code suivant tu peux le supprimer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    myThread = new Thread(new ThreadStart(fonctionThread));
    myThread.Start();
    et tu le remplaces directement par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
          diagnostic = new DiagnosticAffichage(this);
          this.layout.Controls.Add(diagnostic);
          diagnostic.Run();
    Le Invoke() ou BeginInvoke() tu l'appelles dans AppelAffichage(), tu fais un truc du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     public void AppelAffichage(object source, ElapsedEventArgs e)
            {
                if ( this.InvokeRequire)
                {
                     BeginInvoke( AppelAffichage )
                }
                else
                {
                     this.ramLibre.Text = "12";
                }
            }

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2008
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 92
    Par défaut
    La création et la destruction d'un thread sont assez couteux, donc si tu cherches juste à parralleliser une tache, utilises plutot :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ThreadPool.QueueUserWorkItem(o => 
    { 
    // Tache parallle
    } );
    Ce qui est compliqué dans la gestion des threads, c'est leur synchronisation. Dès que tu dois partager des resssources entre plusieurs threads, il faut faire hyper attention.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    Bon alors avec l'aide d'un ami j'ai pu un peu avancé sur le sujet et voilà où j'en suis.

    Ici voici le code de mon form.
    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
     
    public partial class Fenetre : Form
        {
            private FilExecution fil;
     
            public Fenetre()
            {
                InitializeComponent();
                fil = new FilExecution(this);
                fonctionThread();
            }
     
            public FlowLayoutPanel getLayout()
            {
                return this.layout;
            }
     
            private void fonctionThread()
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(fil.temps));
            }
    }
    Du form on crée donc un nouveau thread qui va gérer mon timer voyez donc ici :
    Le timer une fois fini appel une fonction qui va faire appel à la méthode Invoke de mon délégué. Mon délégué lui pointe sur une fonction de diagnostic qui doit géré l'affichage dans mon UserControl inclus dans mon form principal.

    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
     
    class FilExecution
        {
            DiagnosticAffichage diagnostic;
            public delegate void delegue();
            public delegue mydelegue;
            Fenetre fenetre;
     
            public FilExecution(Fenetre a)
            {
                fenetre = a;
                diagnostic = new DiagnosticAffichage();
                fenetre.getLayout().Controls.Add(diagnostic);
                mydelegue = new delegue(callAffichage);
            }
     
            public void temps(object sender)
            {
                System.Timers.Timer temps2 = new System.Timers.Timer();
                temps2.Interval = 200;
                temps2.Elapsed += new ElapsedEventHandler(AppelAffichage);
                temps2.Enabled = true;
                temps2.Start();
            }
     
            public void AppelAffichage(object source, ElapsedEventArgs e)
            {
                mydelegue.Invoke();
            }
     
            public void callAffichage()
            {
                diagnostic.Affichage();
            }
        }
    voilà la fonction :
    ramLibre, processeurPourcentage, disqueLibre & kbytesSec sont des labels de DiagnosticAffichage.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public void Affichage()
            { 
                this.ramLibre.Text = diagnostic.getMemoire();
                this.processeurPourcentage.Text = diagnostic.getProcesseur();
                this.disqueLibre.Text = diagnostic.getDisque();
                this.kbytesSec.Text = diagnostic.getReseau();
            }
    L'erreur porte sur les lignes de cette dernière fonction et évoque :

    Opération inter-threads non valide : le contrôle 'ramLibre' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Que puis je faire ? Je sais que le soucis c'est qu'il fait appel à des variables qui ne sont pas dans son thread mais la méthode de création de thread ne me permet pas de transmettre de variables donc je suis un peu perdu.

    Désolé pour la longueur mais je me devais d'être complet.

  9. #9
    Membre Expert
    Homme Profil pro
    Inscrit en
    Juillet 2007
    Messages
    1 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations forums :
    Inscription : Juillet 2007
    Messages : 1 277
    Par défaut
    Regarde du côté de la méthode Invoke de chaque composant WinForms.

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Par défaut
    Il faut que tu fasses un Invoke dans la fonction Affichage()

    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
     
    public void Affichage()
    {
         if (this.InvokeRequired)
        {
    	this.Invoke(new Action(Affichage));
        }
        else
       {
    	this.ramLibre.Text = diagnostic.getMemoire();
    	this.processeurPourcentage.Text = diagnostic.getProcesseur();
    	this.disqueLibre.Text = diagnostic.getDisque();
    	this.kbytesSec.Text = diagnostic.getReseau();
      }
     
         }
    et tu peux remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
       public void AppelAffichage(object source, ElapsedEventArgs e)
            {
                mydelegue.Invoke();
            }
     
            public void callAffichage()
            {
                diagnostic.Affichage();
            }
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      public void AppelAffichage(object source, ElapsedEventArgs e)
            {
               diagnostic.Affichage();
            }

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    182
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 182
    Par défaut
    Merci bcp c'est ce qu'il me fallait !!

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

Discussions similaires

  1. Communication inter-threads par stdout sous linux
    Par millerf dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 17/07/2007, 11h28
  2. Réponses: 4
    Dernier message: 15/06/2007, 10h41
  3. Communication inter-threads: methode elegante?
    Par jc_isd dans le forum C++
    Réponses: 10
    Dernier message: 17/01/2007, 10h55
  4. [c#]Communication inter thread
    Par chasse dans le forum Windows Forms
    Réponses: 6
    Dernier message: 18/12/2006, 20h45
  5. communication inter-thread en c sous linux
    Par splinternabs dans le forum POSIX
    Réponses: 17
    Dernier message: 22/02/2006, 09h34

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