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 :

Thread et librairie


Sujet :

C#

  1. #1
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut Thread et librairie
    Bonjour à tous,

    Voulant créer organiser un client-serveur dans une librairie pour que ça soit portable pour de futur développements, j'ai crée une classe Client.

    Cette classe fonctionne ou presque car j'ai un Thread d'écoute qui tourne pour vérifier si un message a été reçu. Lorsqu'il en trappe un, il lance un évènement (si il est défini).

    Mon soucis est que je ne comprend pas trop comment résoudre mon problème inter-thread. Ma fenêtre crée un Client et s'abonne à l'évènement mais lorsque je déclenche l'évènement depuis mon Client pour le réceptionner dans la classe qui contient la fenêtre, ça coince. Mon but serais de faire comme on peut faire avec les composants standard, à savoir, je m'abonne puis je défini ce qui dois être fais.

    Voici le 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
     
    // Class client
            public delegate void ReceiveHandler(object sender, string text);
            public event ReceiveHandler ReceiceEventHandler;
    ...
    // Methode de connection
                    _listener = new Thread(new ThreadStart(Receive));
                    _listener.Start();
    ...
    // Methode Receive (du thread)
                        if (message.Length != 0 && ReceiceEventHandler != null)
                        {
                            ReceiceEventHandler(this, message);
                        }
     
    // Class de la fenetre (ça peut etre autre chose comme une console...)
    // Connection   
             _client = new Client(Boite_Serveur.Text, Convert.ToInt32(Boite_Port.Text));
                _client.ReceiceEventHandler += new Client.ReceiveHandler(_client_ReceiceEventHandler);
    ...
     
            void _client_ReceiceEventHandler(object sender, string text)
            {
                if (text.Contains("#liste"))
                {
                    listeConnecte.Items.Clear();
                    string[] S_message = text.Split('|');
                    for (int i = 1; i < S_message.Length; i++)
                    {
                        listeConnecte.Items.Insert(listeConnecte.Items.Count, S_message[i]);
                    }
                }
    ....
    en faite, tout ce passe bien mais arrivé à la méthode "_client_ReceiceEventHandler", dès que j'utilise un élément de la fenêtre, ça explose. Pourtant, lorsque je m'abonne à des évènements dans des librairies ou autre par exemple, je n'ai pas ce problème...

  2. #2
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    On ne peut toucher à une composant visuel qu'à partir du thread qui l'a crée (en général, le thread principal). Vu ta description, ton code _client_ReceiveMachin s'exécuter dans un autre Thread donc boom.
    Pour que ça marche il faut passer dans le thread principal avec Control.Invoke et ça ferai un truc genre
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    if (text.Contains("#liste"))
                {
                    this.Invoke(new MethodInvoker(delegate{
                          listeConnecte.Items.Clear();
                          string[] S_message = text.Split('|');
                          for (int i = 1; i < S_message.Length; i++)
                          {
                              listeConnecte.Items.Insert(listeConnecte.Items.Count, S_message[i]);
                          }
                      }));
                    }
                }

  3. #3
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    Merci mais malheureusement, je connaissais cette solution mais je cherchais à avoir un système plus "propre" . Disons que j'aimerais bien exporter cette petite librairie et tout englober dans un delegate avec invoke...

    Il n'y a pas un moyen de rendre le coté en dehors de la librairie plus propre? à savoir, que la personne voulant utiliser la librairie n'ai pas à tout englober dans un delegate...?

    En même temps, je pensais que c'étais la fenêtre abonné à l'évènement qui en étais le propriétaire (ou qu'il passaient l'un après l'autre...)

  4. #4
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    Citation Envoyé par poussinphp Voir le message
    Disons que j'aimerais bien exporter cette petite librairie et tout englober dans un delegate avec invoke...
    C'est ça que tu appelles plus propre ?!

    Normalement c'est un problème de conception. La lib ne doit pas avoir à accéder à l'interface et si la lib est multithread ou en tout cas n'exécute pas tout ce qu'il faut sur le thread principal, c'est à l'appelant de s'adapter. Tu aura tout le mal du monde à faire la transition de thread à l'intérieur de la lib car il faut toujours que tu aies accès à l'interface (pour que le this.Invoke fonctionne comme voulu) et du coup il faudrait envoyer l'interface à la lib ce qui est tout sauf propre.

    Et quand on s'abonne à un évènement à partir d'un thread, l'évènement n'est pas lancé sur le thread dans lequel il a été inscrit, mais dans le thread qui a généré l'évènement.

  5. #5
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    Je me suis trompé... je voulais dire "et ne pas tout englober dans un delegate avec invoke"

    Tu as raison, je devrais essayer de modifier ma conception mais pour cela, fraudais que je trouve une solution pour récupérer le message simplement et proprement dans ma form sans que ça gêne le reste...

    En tout cas, merci pour les réponses

  6. #6
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par smyley Voir le message
    Et quand on s'abonne à un évènement à partir d'un thread, l'évènement n'est pas lancé sur le thread dans lequel il a été inscrit, mais dans le thread qui a généré l'évènement.
    Il existe pourtant l'interface ISynchronizeInvoke,
    qui permet à un objet de la business layer de lancer ses events sur le thread qui va bien. La DataTable doit probablement l'implémenter, puisqu'un ajout de données à une DataTable dans un thread métier ne fait pas péter une DataGridView.

    Si tu crées un Component, et que tu le rajoutes à une form via designer, il est construit en lui filant en paramètre un IContainer, qui est le Container de la Form ; ce qui affecte la propriété "Site" du contrôle, qui est du type ISynchronizeInvoke.

  7. #7
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    Ce qui reviens donc à passer un composant de l'interface qui aura aussi une méthode Invoke qui pourra faire l'appel. Retour à la case départ.
    Je ne crois pas que ce soit à la lib de se synchroniser mais à l'interface de placer les appels dans le bon thread ...

  8. #8
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par smyley Voir le message
    Ce qui reviens donc à passer un composant de l'interface qui aura aussi une méthode Invoke qui pourra faire l'appel. Retour à la case départ.
    Je ne crois pas que ce soit à la lib de se synchroniser mais à l'interface de placer les appels dans le bon thread ...
    Vu que de toutes façon, le composant métier M a une référence vers le composant graphique G, dès lors que G s'abonne à une méthode de C, il ne paraît pas choquant d'avoir en plus un référence explicite de G vers C. Via une interface, hein, on va pas spaghettiser le truc

    Après, j'ai pu lire beaucoup de critiques concernant les choix de Microsoft vis à vis d'ADO.Net, puisque les designer vont par défaut mettre les DataTable et DataSet dans la form en elle-même, ce qui est pas top d'un point de vue séparation en couche.

    Faudrait que je me penche un peu plus sur ces fameux Component, moi

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

Discussions similaires

  1. threads et librairies dynamiques
    Par Tinkh dans le forum POSIX
    Réponses: 6
    Dernier message: 18/11/2011, 16h33
  2. Librairies utilisation de THREAD
    Par B-NeT dans le forum Visual C++
    Réponses: 3
    Dernier message: 01/07/2008, 10h47
  3. Librairie C++ portable pour Thread
    Par Dam06 dans le forum Linux
    Réponses: 5
    Dernier message: 08/04/2008, 15h07
  4. Probleme de compilation : librairie OT pour thread absente?
    Par Valkirion dans le forum Threads & Processus
    Réponses: 2
    Dernier message: 18/04/2007, 11h07
  5. Librairie OO et portable pour RegExp, Thread, Sockets, etc..
    Par Swoög dans le forum Bibliothèques
    Réponses: 29
    Dernier message: 27/05/2006, 12h29

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