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 :

Evenement et thread : problème de synchronisation ?


Sujet :

Windows Forms

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 9
    Points : 2
    Points
    2
    Par défaut Evenement et thread : problème de synchronisation ?
    Bonjour,

    Mon application dispose :
    - d'une form appellée "MainForm"
    - d'une classe appellée "Session"


    La classe Session gère différent périphérique relié à l'ordinateur.
    La communication avec chaque périphérique se fait dans un thread séparé. (il y a 2 périphériques donc 2 threads).

    Lorsqu'un des périphériques communique avec l'ordinateur, le thread de
    communication fait appel à une méthode de la classe Session nommée
    "traitementReception(string data)"
    -> cette méthode envoi un événement nommé "AfficheData" qui est récupéré par la MainForm. Lorsque la forme reçoit cet événement, elle affiche un panel d'information à l'utilisateur.

    Voici mon problème :
    Au démarrage de l'application, lorsqu'un périphérique communique, ma
    MainForm détecte l'événement envoyé par la classe Session et affiche
    correctement le panel d'informations.

    Par contre, lorsque mon application "tourne" depuis plusieurs minutes
    (environ une Dizaine de minute) sans aucune activité et qu'un périphérique communique avec l'ordinateur, un délais d'environ 15s est nécessaires pour que ma MainForm réagisse et affiche le panel d'information !

    Après tous mes tests pour palier à ce problème, je ne vois vraiment pas comment y remédier.
    Est-ce un problème de synchro entre le thread principal et les threads de communication ?
    Est-ce qu'une Form peut se mettre en état "endormi" ? et ne répondre que sous un délais de plusieurs secondes lors de la réception d'un événement ?

    Pouvez-vous m'aider ?

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    aucune raison pour que ca soit pas instantané, à part le code que tu as mis

    mets des points d'arrêts pour voir ce qui se passe
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Oui, j'ai bien essayé de debugger avec des points d'arret ou des fichiers de log mais mon problème ne se produit que lorsqu'il y a une inactivité sur le PC d'une dizaine de minutes...
    Sinon, en utilisation "normal", je n'ai jamais ce retard de 10 à 20s !! C'est incomprehensible

    Avant de poster mon problème j'ai vraiment essayé de le resoudre par tous les moyens que je connais (qui se limitte aux points d'arrêts et au fichier de log)

    La MainForm n'est pas très compliqué, je repond simplement à des évenements. Par contre, j'ai un timer sur la Form... mais je ne pense pas que le pb soit lié

  4. #4
    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
    Comment et quand ta form s'abonne t'elle à l'événement de ta classeSession ?
    Que fait la méthode de ta form abonnée à cet event ?
    Pourquoi as-tu un timer ? Est-il lié à la communication entre la form et ton objet Session ?
    ಠ_ಠ

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par Guulh Voir le message
    Comment et quand ta form s'abonne t'elle à l'événement de ta classeSession ??
    Dès le demarrage de l'application

    Que fait la méthode de ta form abonnée à cet event ?
    Elle change les propriétés "visible" de deux panels

    Pourquoi as-tu un timer ? Est-il lié à la communication entre la form et ton objet Session
    Le timer sert à afficher periodiquement une propriété de la classe session


    Pour clarifier, voici le code "simplifié" de la classe session et de la form :

    Classe session :

    - Lancement de la méthode "testConnections" par un thread (permet de tester si une connexion Internet est active.
    - La méthode "testConnections" demarre la communication du périphérique (Monnayeur) par la méthode "startMonnayeur". Cette méthode est également lancée par un thread.
    - Lorsque le monnayeur detecte l'insertion d'une pièce, il fait appel à la méthode "creditInserer" de la classe Session.
    -> à ce moment, la méthode "creditInserer" envoi un evenement récupéré par la 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
    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
    public Session ()
    {
                InitializeTimer();
                //Lancement thread de test de connexion Internet et Serveur
                testConnectionThread = new Thread(new ThreadStart(testConnections));
                // Lancement du thread
                testConnectionThread.Start(); 
    }    
     
    private void testConnections()
    {
     
                HttpWebRequest request;
                HttpWebResponse response;            
     
                //Envoi evenement aucune connexion internet
                NoInternetConnection();
                Thread.Sleep(2000);
     
                //Test connexion serveur au démarrage
                while (true)
                {
                    try
                    {
                        // Create an HTTP Web request
                        request = (HttpWebRequest)HttpWebRequest.Create("http://www.monserveur.com");
                        // Perform GET
                        response = (HttpWebResponse)request.GetResponse();
                        if (HttpStatusCode.OK == response.StatusCode)
                        {
                            //HTTP = 200, close the request and return true
                            response.Close();
                            //Log connexion Serveur
                            this.serveurConnection = true;                        
                            break;
                        }
                        else
                        {
                            this.serveurConnection = false;
                        }
     
                    }
                    catch (WebException)
                    {
                        // Deffinitely offline
                        this.serveurConnection = false;
                    }
                    //Si aucune connexion, attente 20s avant autre essai (ping)
                    Thread.Sleep(20000);                
                }
     
     
                //Première connexion Ok. Test en continue de l'état de connexion Internet Windows
                while (true)
                {
                    try
                    {
                        //Test connexion internet
                        long lngFlags = 0;
                        int temp_int = (int)lngFlags;
                        if (InternetGetConnectedState(ref temp_int, 0))
                        {                        
                            if (this.internetConnection == false)
                            {                            
                                //Envoi evenement connexion internet Ok
                                InternetConnectionOk();                            
                                    this.startMonnayeur();
     
                            }                                               
                        }
                        else
                        {                        
                            if (this.internetConnection == true)
                            {
                                this.internetConnection = false;
                                this.serveurConnection = false;
                                //Envoi evenement aucune connexion internet
                                NoInternetConnection();                            
     
        this.StopComMonnayeur();
     
                            }                        
                        }                    
                    }
                    catch (WebException)
                    {
                        // Deffinitely offline                                        
                    }
                    Thread.Sleep(2000);               
                }
    }    
     
    //Demarrage monnayeur
    private void startMonnayeur()
    {       
                //Initialisation communication Monnayeur
                try
                {
                    //Initialisation communication monnayeur (COM via un thread)
                    monnayeur = new Monnayeur(this);
                    this.monnayeurConnected = monnayeur.initComMonnayeur ();
     
                        //Lancement de la méthode de reception
                        comMonnayeurThread = new Thread(new ThreadStart(StartComMonnayeur));
     
                        // Lancement du thread
                        comMonnayeurThread.Start();
     
                        this.isMonnayeurStarted = true;
                }
                catch (Exception err)
                {
                    //Log                 
                }
    }
     
     
    public void creditInserer(double valeurCredit)
    {                                                               
                //Declenchement evenement debut de session IHM
                StartSession();
                //Demarrage session
                this.startTimerSession(false);                                        
                //Envoi evenement credit inséré
                CreditInserer();           
    }

    Classe de la Form :

    - Abonnement aux évenements
    - Affichage d'un panel à la reception de l'evenement

    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
    public MainForm()
    {         
                InitializeComponent();
                this.session = new Session ();                        
                CheckForIllegalCrossThreadCalls = false;                        
                //Souscription à l'evenement fin de session
                this.session.EndSession += new Session.EndSessionEventHandler(OnEndSession);
                //Souscription à l'evenement debut de session
                this.session.StartSession += new Session.StartSessionEventHandler(OnStartSession);            
                //Souscription à l'evenement aucune connexion internet
                this.session.NoInternetConnection += new Session.NoInternetConnectionEventHandler(OnNoInternetConnection);
                //Souscription à l'evenement connexion internet Ok
                this.session.InternetConnectionOk += new Session.InternetConnectionOkEventHandler(OnInternetConnectionOk);            
    }
     
     
    private void OnStartSession()
    {
                this.BeginInvoke(new InvokeDelegate(AfficheInformation));  
    }
     
    public void AfficheInformation ()
    {                     
     
                this.pInfoTarif.Visible = false;
    this.pInfoSession.Visible = true;            
    }

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Je n'arrive pas à m'en sortir !
    Personne à d'idée ?

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    27
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 27
    Points : 33
    Points
    33
    Par défaut
    Je suis pas Nostradamus, mais j'ai l'intuition que c'est le
    qui doit être en cause.
    Sinon, plutôt que d'utiliser des Thread.Sleep (qui risque de te bloquer les threads), je te conseillerais de passer par les ManualResetEvent

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Non, le thread.sleep(20000) s'exécute une seule fois au démarrage de l'appli. Je sais que tu n'es pas nostradamus mais j'ai comme même testé bcp de solution avant de poster mon pb...

    Encore une fois, quand j'utilise mon application, au démarrage, tout fonctionne à merveille ! J'ai un problème lorsque mon application et le PC est inutilisé pendant plusieurs minutes ; l'affichage reste bloqué 10/20 secondes après avoir inséré une pièce dans le monnayeur. Par contre, si je clic quelque part à l'écran avant d'insérer la pièce, je n'ai aucun retard d'affichage !!

    Je ne connais pas "ManualResetEvent", je vais me renseigner.

  9. #9
    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
    C'est l'event de début de session qui te pose souci ? Il doit n'arriver qu'une fois, non ?

    Tu peux déjà voir si le problème vient de la partie winform ou de ta partie métier en mettant loggant l'heure et date dans les méthodes OnStartSession et AfficheInformation de ta form et creditInserer de ton objet Session. S'il y a un décalage entre les heures de ces appels, c'est qu'il y a un problème côté UI...

    Mais le mécanisme d'events est purement synchrone, donc je vois pas trop...

    Tant que j'y suis : dans ta classe Session, tu appelles directement les events, sans tester s'ils sont nuls, ce qui est le cas quand aucune méthode n'est abonnée. Et là, NullReferenceException
    ಠ_ಠ

  10. #10
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 9
    Points : 2
    Points
    2
    Par défaut
    Tu as trouvé l'origine Guulh !
    J'ai testé les différentes parties de mon code par des logs dans un fichier text.
    Le retard provient bien de la partie métier et non de l'UI. Les events fonctionnent très bien. Il y a une méthode que j'appel dans la méthode "creditInserer" qui semble être la cause de ce retard. Je vais continuer le debbug aujourd'hui.
    Ce que j'ai vraiment du mal à comprendre, c'est pourquoi je n'ai pas de retard quand j'utilise l'application avant d'insérer une pièce (un seul clic à l'écran suffit)...

Discussions similaires

  1. Réponses: 13
    Dernier message: 11/06/2015, 15h51
  2. Problème de synchronisation entre Thread et VCL
    Par Jipété dans le forum Débuter
    Réponses: 33
    Dernier message: 21/05/2012, 11h14
  3. Réponses: 4
    Dernier message: 17/02/2010, 23h21
  4. [THREAD] Problème synchronisation
    Par goddet dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 25/10/2006, 09h16
  5. problème de synchronisation de thread
    Par youp_db dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 11/10/2006, 11h34

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