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 :

Interface graphique et thread producteur-consomateur


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 3
    Par défaut Interface graphique et thread producteur-consomateur
    Bonsoir, pour la première fois je dois utiliser les threads dans un programme que je dois réaliser dans le cadre de mes études.
    Je voudrais créer une fenêtre dans laquelle il y aurait 2 textbox :
    TextBox1 dans laquelle j'entre des caracteres
    Textbox2 qui récupère bêtement ce que j'entre dans la TextBox1

    En fait, j'avais pensé créer un thread PRODUCTEUR pour la première TextBox qui lorsque je tape un caractère dans TextBox1 , stocke ce caractère dans une file, puis se bloque.

    Enfin le second thread CONSOMATEUR "prend la main" lorsqu'il y a un caractère dans la file, le récupère , et l'affiche dans la TextBox2

    Est ce possible ?

    Ci-dessous un code C# que j'ai réalisé grâce à l'aide MSDN.
    C'est une application console.

    Le thread PRODUCTEUR me demande de taper une lettre.
    Il la stocke dans une structure QUEUE.
    Il passe la main au thread CONSOMMATEUR.
    Le thread Consommateur récupère le caractère et l'affiche.
    D'ailleurs je dois "endormir" le main afin de laisser la place aux threads PRODUCTEUR et CONSOMMATEUR...
    Je me demmande donc comment cela est réalisable en interface graphique car il y a le main ainsi que les forms ( qui s'execute en boucle ? ) bref je suis perdu...

    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Collections;
     
     
    public class SyncEvents
    {
        public SyncEvents()
        {
     
            _newItemEvent = new AutoResetEvent(false);
            _exitThreadEvent = new ManualResetEvent(false);
            _eventArray = new WaitHandle[2];
            _eventArray[0] = _newItemEvent;
            _eventArray[1] = _exitThreadEvent;
        }
     
        public EventWaitHandle ExitThreadEvent
        {
            get { return _exitThreadEvent; }
        }
        public EventWaitHandle NewItemEvent
        {
            get { return _newItemEvent; }
        }
        public WaitHandle[] EventArray
        {
            get { return _eventArray; }
        }
     
        private EventWaitHandle _newItemEvent;
        private EventWaitHandle _exitThreadEvent;
        private WaitHandle[] _eventArray;
    }
    public class Producer
    {
        public Producer(Queue<char> q, SyncEvents e)
        {
            _queue = q;
            _syncEvents = e;
        }
        // Producer.ThreadRun
        public void ThreadRun()
        {
            int count = 0;
            Random r = new Random();
     
            while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))
            {
                lock (((ICollection)_queue).SyncRoot)
                {
                    //int tp = r.Next(0, 100);
                    char tp;
                    while (_queue.Count < 1)
                    {
                        Console.WriteLine("Taper lettre :");
                        tp = Convert.ToChar( Console.ReadLine());
                        _queue.Enqueue(tp);
                        Console.WriteLine("je produit " + tp);
                        _syncEvents.NewItemEvent.Set();
                        count++;
                    }
     
     
                }
     
            }
            Console.WriteLine("thread producteur: produced {0} items", count);
        }
        private Queue<char> _queue;
        private SyncEvents _syncEvents;
    }
     
    public class Consumer
    {
        public Consumer(Queue<char> q, SyncEvents e)
        {
            _queue = q;
            _syncEvents = e;
        }
        // Consumer.ThreadRun
        public void ThreadRun()
        {
            int count = 0;
            while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)
            {
                lock (((ICollection)_queue).SyncRoot)
                {
     
                        char item = _queue.Dequeue();
                        Console.WriteLine("Je consome " + item);
     
     
                }
                count++;
     
            }
            Console.WriteLine("Consumer Thread: consumed {0} items", count);
        }
        private Queue<char> _queue;
        private SyncEvents _syncEvents;
    }
     
    public class ThreadSyncSample
    {
        private static void ShowQueueContents(Queue<char> q)
        {
            lock (((ICollection)q).SyncRoot)
            {
                foreach (char item in q)
                {
                    Console.Write("{0} ", item);
                }
            }
            Console.WriteLine();
        }
     
        public static void Moul()
        {
            Queue<char> queue = new Queue<char>();
            SyncEvents syncEvents = new SyncEvents();
     
            Console.WriteLine("Configuration des threads.");
            Producer producteur = new Producer(queue, syncEvents);
            Consumer consomateur = new Consumer(queue, syncEvents);
            Thread Thread_producteur = new Thread(producteur.ThreadRun);
            Thread Thread_consomateur= new Thread(consomateur.ThreadRun);
     
            Console.WriteLine("Lancement  des threads producer and consumer...");
            Thread_producteur.Start();
            Thread_consomateur.Start();
     
            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("le main s'endort et laisse la place au producteur consomateur durant 5min ");
                Thread.Sleep(500000);
     
                ShowQueueContents(queue);
            }
     
            Console.WriteLine("Signaling threads to terminate...");
            syncEvents.ExitThreadEvent.Set();
     
            Thread_producteur.Join();
            Thread_consomateur.Join();
            Console.ReadLine();
        }
     
    }
     
    namespace thread
    {
        class Program
        {
            static void Main(string[] args)
            {
                ThreadSyncSample.Moul();
     
            }
        }
    }

    Voici une trace de l'exécution du programme :

    Lancement des threads producer and consumer
    Taper lettre :
    a
    je produit a
    je consomme a

    Taper lettre :
    b
    je produit b
    je consomme b

    Taper lettre :
    c
    je produit c
    je consomme c

    ....

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Pas de bol t'as pas pris le bon exemple! Les GUI sont monothreadés: seul le thread qui a construit la GUI peut accéder et modifier les éléments graphiques
    Alors ton truc est possible mais saches que tu auras une file d'attente (le dispatcher) pour modifier le GUI.

    Manifestement tu as un projet console. Le plus simple est de créer un projet winform.
    Dans le constructeur de ta fenetre tu crées ton queue, le consommateur, tu le lances. (Ici pas de producteur car en fait c'est la window le producteur)
    Ensuite tu t'abonnes à l'évenement TextChanged (ou un truc du genre) de TextBox1. Dans l'handler de cet évenement tu ajoutes un élément à ta queue comme tu fais avec ton producteur actuel.
    Ton thread consumer va s'en apercevoir. Il faut qu'il demande au dispatcher de ta window de mettre a jour le contenu de textbox2 et le tour est joué!

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

    Informations forums :
    Inscription : Décembre 2010
    Messages : 3
    Par défaut
    Merci beaucoup PitMaverick78
    En faite l'appli est toute bête il s'agit de crypter une phrase avec la méthode vignere.
    Et le prof (sans savoir si il était sérieux) a balancé qu'il voulait de l'interface graphique, plusieurs processus ( le but étant de voir la phrase que l'on tape dans TExtBox1, se coder en direct dans la textBox2...) mais bon tout cela me parait bien compliqué.
    Je vais plancher sur ta piste et encore une fois merci.

  4. #4
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Sans thread c'est tout a fait possible et beaucoup plus simple.
    Tu fais une form toute bete avec deux textbox:
    Tu t'abonnes a TextChanged de Textbox1
    Dans l'handler tu dis Textbox2.Text = MaMethodeQuiEncrypte(Textbox1.Text)
    Et zou c'est réglé!

    Je sais pas quel age a ton prof mais il en est peut être resté a des technos un peu plus agées qui nécessitait effectivement de se creuser un peu plus pour un banal GUI

  5. #5
    Membre éprouvé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 627
    Par défaut
    L'intérêt de cet exercice, c'est sur le thread qui est chargé de réaliser un traitement lourd, un hashage bête d'une chaine c'est pas un souci, sur un fichier c'est autre chose, et le thread de l'UI n'est pas là pour ça. Donc oui pour un cas bateau c'est pas un souci, mais sur un traitement conséquent c'est autre chose...

    Dans ton cas, si tu le veux threadé, le consommateur doit appeler le dispatcher de l'UI pour afficher la valeur traitée...

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

    Informations forums :
    Inscription : Décembre 2010
    Messages : 3
    Par défaut
    Merci à vous, je vais essayer de faire des recherches sur ce que vous appellez le 'dispatcher'.
    Je ne mis connais pas trop ...
    Je ne vois pas ce que c'est!
    Si vous avez d'autre remarque n'hesitez pas car cela m'aide.

Discussions similaires

  1. Utilisation des threads et interface graphique
    Par cyberspy2999 dans le forum Débuter
    Réponses: 1
    Dernier message: 20/02/2011, 21h27
  2. Socket, Thread et interface graphique
    Par archer dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 07/01/2009, 00h48
  3. Thread et interface graphique
    Par archer dans le forum C#
    Réponses: 5
    Dernier message: 02/04/2008, 06h06
  4. Réponses: 1
    Dernier message: 01/02/2008, 12h59
  5. Interface graphique et thread
    Par freddyboy dans le forum Windows Forms
    Réponses: 2
    Dernier message: 27/06/2007, 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