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 :

Partage variable entre Threads


Sujet :

C#

  1. #1
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut Partage variable entre Threads
    Bon,
    J'ai une application Client/Serveur,
    Coté client j'ai utilisé un thread (ReceivePacket) qui reçoit le message venant du serveur. J'utilise Windows.Form pour l'interface. Le probleme c'est que le compilateur me prévient d'invalidité d'utilisations des objets entre thread quand je fais appele aux composants des Form (SplitContainer, ....) dans le thread (ReceivePacket), Or j'ai déjà partagé l'objet au moyen de XX.start(ObjetApartager)???
    Est quelqu'un aura un idée de cause de cette problème?

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 201
    Points : 196
    Points
    196
    Par défaut
    Je ne suis pas sur de tout à fait comprendre ce que tu cherches à faire.

    Pour faire "dialoguer" deux classes dans des threads différents, tu peux utiliser les délégués, et la méthode Invoke.

    Si tu as une variable/propriété partagée entre deux threads, tu peux faire un lock, pour en assurer la sûreté d'accès.

  3. #3
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut
    C'est la deuxième proposition qui me semble très utile.
    Mais que fait exactement lock?

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    201
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 201
    Points : 196
    Points
    196
    Par défaut
    Je vais essayer de ne pas dire de bétises

    En gros, lock interdit à deux thread de venir dans le bout de code concerné en même temps. Et à la place créer une liste d'attente.

    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
    int GetCount()
    {
        lock(_list)
        {
            return _list.Count;
        }
    }
     
    void Add(object item)
    {
        lock(_list)
        {
            _list.Add(item);
        }
    }
    En faisant cela, tu t'assure qu'aucun thread ne viennent ajouter des données dans _list, pendant que tu compte ce qu'il y a dedans.
    De plus deux thread ne peuvent ajouter en même temps des données dans _list.

  5. #5
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    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
    Points : 2 331
    Points
    2 331
    Par défaut
    Tu partages des objets graphiques (Form ==> Winform ?) entre threads ? Dans ce cas là je t'arrête, il ne doivent être manipulés que depuis le thread UI ! D'où le message indiquant que ce composant appartient à un autre thrad !

  6. #6
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut
    Citation Envoyé par Arnard Voir le message
    Tu partages des objets graphiques (Form ==> Winform ?) entre threads ? Dans ce cas là je t'arrête, il ne doivent être manipulés que depuis le thread UI ! D'où le message indiquant que ce composant appartient à un autre thrad !
    Donc que faire alors? Mon but c'est de rendre visible le SplitContainer + TreeView + ListView quand le client reçoit des messages ACK venant du serveur car je compte le traiter dans la deuxième thread (ReceivePacket)

  7. #7
    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 : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    Le multi thread avec une UI est un peu particulier. Lorsqu'un thread en arrière plan souhaite effectuer une modification sur un objet de l'UI, il faut qu'il ajoute ca à la liste des taches à faire pour le thread de l'UI. Il suffit de récuperer une instance de contrôle comme par exemple myForm (une instance d'un formulaire) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    myForm.Invoke(()=>{myCheckbox.Checked=true;});
    A noter que dans le délégué il ne faut executer que du code de rafraichissement de l'ui, sinon tu freezes ton ui.

  8. #8
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Bonjour, en utilisant Control.Invoke/BeginInvoke (ou le Dispatcher pour WPF).

    EDIT : Oups, trop tard.

  9. #9
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut
    Citation Envoyé par Nathanael Marchand Voir le message
    Le multi thread avec une UI est un peu particulier. Lorsqu'un thread en arrière plan souhaite effectuer une modification sur un objet de l'UI, il faut qu'il ajoute ca à la liste des taches à faire pour le thread de l'UI. Il suffit de récuperer une instance de contrôle comme par exemple myForm (une instance d'un formulaire) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    myForm.Invoke(()=>{myCheckbox.Checked=true;});
    A noter que dans le délégué il ne faut executer que du code de rafraichissement de l'ui, sinon tu freezes ton ui.
    Donc j'utilise mon thread, avec partages des Objets entre thread avec Start et où je met cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    myForm.Invoke(()=>{myCheckbox.Checked=true;});

  10. #10
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 493
    Points
    5 493
    Par défaut
    Tu places tout simplement cette ligne à l'endroit où tu avais normalement écrit "myCheckbox.Checked = true" dans ton worker thread.

    Considère Invoke/BeginInvoke comme un wrapper à utiliser pour effectuer une action UI depuis un autre thread que celui de l'UI : ces méthodes forcent l'exécution du délégué spécifié sur le thread UI plutôt que sur le thread appelant.

    C'est un pattern qui élimine tout besoin de synchronisation en garantissant que tout accès fait depuis un autre thread que l'UI lèvera une exception. Ses forces sont sa simplicité de conception et d'utilisation, ses faiblesses sont un impact sur les performances et/ou la réactivité plus important qu'un système traditionnel bien conçu et bien utilisé.


    PS : l'objet fourni en argument à Thread.Start est simplement un paramètre fourni à la méthode de ton thread, il ne bénéficie aucunement d'un quelconque traitement particulier qui assurerait une synchronisation lors d'un accès parallèle par deux threads. C'était peut-être clair pour toi mais à la relecture de certaines de tes phrases je me suis dit que tu avais peut-être compris cela de travers. Au cas où...

  11. #11
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut
    Merci pour pour l'aide, mais pour être clair (je suis un peu débutant en C Sharp).Est que vous pouvez illustrer par des exemples de codes.
    Voici mon code Thread "ReceivePaquet" que je doit utiliser l'objet SplitContainer de l'UI :
    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
     
     //Methode de Connection au serveur
            public static void  startConnectionServer(String ipAddres)
            {
                try
                {
                    Thread threadMessageReceive = new Thread(receiveMessageTreat);
                    serveur = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    serveur.Connect(new IPEndPoint(IPAddress.Parse(ipAddres), 7777));
     
                    msgOut = ASCIIEncoding.Default.GetBytes(Protocole.DEMAND_CONNECTION);
                    //Demande Authorisation
                    serveur.Send(msgOut);
                    ////////////Lancement du thread lisant les données entrant////////////////////
                    DataThread data = new DataThread(splitContainer1, serveur);
                    threadMessageReceive.Start((object)data);
                }
                catch (System.Net.Sockets.SocketException)
                {
                    Console.WriteLine("Erreur de connexion");
                }
                catch (System.ArgumentException)
                {
                    Console.WriteLine("Erreur de connexion");
                }
                catch (System.InvalidOperationException)
                {
                    Console.WriteLine("Erreur de connexion");
                }
     
            }
            /***********************************METHODE THREAD RECEIVER************************************/
     
     
            public static void receiveMessageTreat(object infos)
            {
                DataThread data = (DataThread)infos;
                SplitContainer split = data.sp;
                Socket server = data.sock;
     
     
                /********************************TRAITEMENT DU MESSAGE****************************/
                while (true)
                {
                    //Reception des paquets!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    try
                    {
                        int n = serveur.Receive(msgIn);
                    }
                    catch (SocketException ev)
                    {
                        break;
                    }
                    string s = ASCIIEncoding.Default.GetString(msgIn);
                    if (s.Contains(Protocole.DEMAND_ACK))
                    {
                        split.Visible = true;//Voici L'ERREUR en utilisant l'objet de L'UI
                    }
     
     
                    Thread.Sleep(10);
                }
     
            }

  12. #12
    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 : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    split.Invoke(()=>{split.Visible = true;});

  13. #13
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut
    J'ai copié le code mais ce donne des erreurs
    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
     
     
                /********************************TRAITEMENT DU MESSAGE****************************/
                while (true)
                {
                    //Reception des paquets!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    try
                    {
                        int n = serveur.Receive(msgIn);
                    }
                    catch (SocketException ev)
                    {
                        break;
                    }
                    string s = ASCIIEncoding.Default.GetString(msgIn);
                    if (s.Contains(Protocole.DEMAND_ACK))
                    {
                        split.Invoke(()=>{split.Visible = true;});
                    }
    et voici l'erreur,
    Error 2 Invalid expression term ')' D:\Telecom Unit\Practice\Programming\C#\RemoteAcces_Project\ClientRemote\ClientRemote\Form1.cs 90 35 ClientRemote
    Error 3 Invalid expression term '>' D:\Telecom Unit\Practice\Programming\C#\RemoteAcces_Project\ClientRemote\ClientRemote\Form1.cs 90 37 ClientRemote
    Error 4 ) expected D:\Telecom Unit\Practice\Programming\C#\RemoteAcces_Project\ClientRemote\ClientRemote\Form1.cs 90 38 ClientRemote
    Error 5 Invalid expression term ')' D:\Telecom Unit\Practice\Programming\C#\RemoteAcces_Project\ClientRemote\ClientRemote\Form1.cs 90 61 ClientRemote

  14. #14
    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 : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    Quelle version de .Net ?

  15. #15
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut Reponse au Discussion
    D'aprés le MSDN 2005 et Visual Studio 2005, La version de Framework .NET utilisé est 2.0.

  16. #16
    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 : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    Ah c'est pour ca que y'a pas de lambda expressions.
    Bon ben alors faut faire ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    split.Invoke(delegate(){split.Visible = true;});

  17. #17
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut Reponse au Discussion
    Il y en a toujours, (erreur)
    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
     
    /***********************************METHODE THREAD RECEIVER************************************/
     
     
            public static void receiveMessageTreat(object infos)
            {
                DataThread data = (DataThread)infos;
                SplitContainer split = data.sp;
                Socket server = data.sock;
     
     
                /********************************TRAITEMENT DU MESSAGE****************************/
                while (true)
                {
                    //Reception des paquets!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    try
                    {
                        int n = serveur.Receive(msgIn);
                    }
                    catch (SocketException ev)
                    {
                        break;
                    }
                    string s = ASCIIEncoding.Default.GetString(msgIn);
                    if (s.Contains(Protocole.DEMAND_ACK))
                    {
                        //ERREUR D'UTILISATION DES COMPOSANTS UI
                        split.Invoke(delegate() { split.Visible = true; });
                    }
    Et l'erreur :
    Error 1 The best overloaded method match for 'System.Windows.Forms.Control.Invoke(System.Delegate)' has some invalid arguments D:\Telecom Unit\Practice\Programming\C#\RemoteAcces_Project\ClientRemote\ClientRemote\Form1.cs 90 21 ClientRemote
    Error 2 Argument '1': cannot convert from 'anonymous method' to 'System.Delegate' D:\Telecom Unit\Practice\Programming\C#\RemoteAcces_Project\ClientRemote\ClientRemote\Form1.cs 90 34 ClientRemote

  18. #18
    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 : 38
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    Bigre je suis pas habitué a de si vieilles versions

    Cette fois ci, c'est la bonne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    split.Invoke(new MethodInvoker(delegate { split.Visible = true; }));

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 537
    Points : 369
    Points
    369
    Par défaut
    Sinon pourquoi ne pas simplement utiliser un backgroundworker?

  20. #20
    Membre habitué

    Homme Profil pro
    Developpeur
    Inscrit en
    Mars 2011
    Messages
    115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Mars 2011
    Messages : 115
    Points : 188
    Points
    188
    Par défaut Suite au Discussion
    OK! Ça marche. Merci à vous. Mais j voudrai juste savoir la signification exacte de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    split.Invoke(new MethodInvoker(delegate { split.Visible = true; }));
    Et encore merci pour le tuto backgroundworker

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Partager des variables entre Threads
    Par ToTo13 dans le forum Concurrence et multi-thread
    Réponses: 7
    Dernier message: 01/04/2010, 16h09
  2. partage de variables globlales entre threads
    Par ikuzar dans le forum Débuter
    Réponses: 7
    Dernier message: 02/09/2009, 15h43
  3. Partager variables entre plusieurs sessions ?
    Par fredtheman dans le forum Langage
    Réponses: 7
    Dernier message: 16/05/2008, 21h07
  4. partage d'une variable entre plusieurs threads
    Par baedal dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 27/02/2008, 20h33
  5. Partager boolean entre Threads
    Par Flipper_fk dans le forum Concurrence et multi-thread
    Réponses: 3
    Dernier message: 26/04/2007, 13h51

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