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

Dotnet Discussion :

Multithreading et Forms figée


Sujet :

Dotnet

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Par défaut Multithreading et Forms figée
    Bonjour,
    je suis en train de développer ma première application Client/Serveur qui consiste à balancer des alertes aux utilisateurs de l'entreprise.

    d'un coté j'ai mon serveur qui interroge une base de données, qui écoute les connexions des client et leur balance toutes les 10 secondes des messages d'alerte (s'il y en a).
    Le coté serveur fonctionne parfaitement.

    du coté client, j'ai un Winform caché (ou non, on peut l'afficher si l'on veut) dont une icône est affichée dans le systray.
    Ce client possède un thread 'TCP' qui se connecte au serveur et écoute ses messages.
    Lorsque ce thread reçoit un message, il génère un event, que le Winform client consomme.
    le Client contient un 'List<popup>', quand il reçoit l'event dont j'ai parlé précédemment, il crée un popup (winform), l'ajoute dans sa liste et l(les)'affiche(s) en bas à droite de l'écran.
    Tout cela fonctionne SAUF QUE : Le popup s'affiche mais reste figé, ne dessine pas tous ses composants, est non cliquable avec un waitcursor en permanence quand je passe la souris dessus;
    Aucune erreur n'est générée.
    Comme si son thread était complètement arrêté.
    Normalement, mon popup a un timer qui se déclenche toutes les demi-secondes pour le faire clignoter, j'ai beau mettre un point d'arret sur le callback du timer, il n'est jamais déclenché. (et pourtant quand j'utilise ces popups indépendamment ils clignotent bel et bien).

    Est-ce car ces popups sont créés par un event généré par un autre thread ?
    Dans tous les cas, quand mon programme d'alerte était monothread (le client récupérait lui même les infos de la base de données) tout fonctionnait très bien.
    Difficile de donner un bout de code vu la taille du projet.

    et j'ai beau mettre des .InvokeRequired .Invoke() partout le problème reste (de toute manière aucune erreur n'est générée)
    Si quelqu'un s'est déjà retrouvé devant un tel problème et a une idée je suis très intéressé

  2. #2
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Par défaut
    Je me suis amusé à faire un diagramme basique représentant le programme :
    Nom : Diagramme_Basique.png
Affichages : 165
Taille : 54,6 Ko

    je pense que c'est parce que l'Event Message_Recu est envoyé depuis un autre thread (Ecoute_Donnees) que ca fige mes popups, mais je n'ai aucune idée de comment corriger le problème.

  3. #3
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Par défaut
    Vu que personne n'a l'air d'avoir d'idée, j'ai décidé de simplifier mon programme au max pour pousser des tests.

    j'ai fait deux tests :

    Le plus simple fonctionne, 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
     
    static void Main()
            {
                    Configuration();
     
                    Affiche_Popup_Bidon();
     
                    Application.Run();
            }
     
    static void Affiche_Popup_Bidon()
            {
                DataTable dt_truc = new DataTable("truc");
                string requete = "SELECT * FROM [1fo_Messages]";
                Outils_BDD.Utiles.Recup_Requete_DataTable(dt_truc, requete, _connexions["1fo_PS"], true, true); //une chtite fonction à moi qui récupère le contenu de la requete dans une datatable
                Popup_Note pn_truc = new Popup_Note(new Message(dt_truc.Rows[0]), _delaiRePopup_Rouge, _delaiRePopup_Orange, _delaiRePopup_Vert);//un popup de type 'Form' qui prend en entrée une datarow représentant un message
                pn_truc.Affiche(true);
            }
    Cette version récupère le premier message venu, me crée un popup et l'affiche; mon popup apparait bien ainsi que ses différents controls, le message est visible et il clignote (fonctionnement interne au popup dû à un timer)

    J'ai ensuite ajouté ma couche réseau dans le 'Main'. La classe Client se connecte au serveur (ici 127.0.0.1 car le serveur tourne pour le moment sur mon poste pour les tests) puis, via un thread, écoute le réseau. Quand la classe Client reçoit un message (qui n'est autre qu'un datatable, mais ici on s'en fout...) elle génère un événement auquel le Main est abonné. Quand le Main consomme cet évènement, il lance simplement la même fonction qu'avant : Affiche_Popup_Bidon().
    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
     
    static void Main()
            {
                    Configuration();
     
                    //Affiche_Popup_Bidon();
                    Outils_ClientServeur.Client monClient = new Outils_ClientServeur.Client("127.0.0.1", TaillesPackets.ko512, true);
                    monClient.MessageRecu += monClient_MessageRecu;
     
                    Application.Run();
            }
     
     private static void monClient_MessageRecu(object sender, string e)
            {
                Affiche_Popup_Bidon();
            }
    Là, le popup apparait, mais figé ! ses controls sont figés ou n'apparaissent pas, rien ne clignote...
    j'ai fait exprès d'exécuter la même méthode Affiche_Popup_Bidon() afin de bien démontrer que le popup lui-même n'est pas en cause, mais que c'est parce qu'il est affiché depuis un event généré par un autre thread.

    Quelque chose m'échappe t'il ?

  4. #4
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Par défaut
    Encore plus simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    static void Main()
            {
                    System.Threading.Timer machin = new System.Threading.Timer(new System.Threading.TimerCallback(bidule),null,0,5000);
     
                    Application.Run();
            }
     
            static void bidule(object state)
            {
                Form burp = new Form();
                burp.Show();
            }
    ici, le code est censé m'afficher une simple Form vide toutes les 5 secondes.
    C'est bien le cas, mais toutes les Forms sont figées !?¿ !!!!

    Et je n'arrive pas à trouver de doc sur ce simple cas

  5. #5
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Par défaut
    Visiblement, dans le dernier cas corrige le problème.

    je vais me contenter de ça à défaut d'explications

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 203
    Par défaut
    déjà il test interdit de créer des forms sur un autre thread que le thread principal, et le threading.timer est sur un autre thread
    utilises plutot System.Windows.Forms.Timer et tes fenetres ne seront pas figées

    et faire des choses avant le application.run (visuelles j'entends) je reste sceptique
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Membre chevronné
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2005
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2005
    Messages : 482
    Par défaut
    Salut, et déjà merci pour ta réponse;

    afficher des trucs avant le Application.Run() ne pose absolument aucun problème, tu peux tester
    d'ailleurs le Affiche_Popup_Bidon() placé avant est bien le seul test qui fonctionne.

    ensuite, pour le dernier test ou j'utilise le Timer, il était surtout pour voir d'où pouvait provenir ce freeze.
    Le but est bel et bien de simplement consommer un event (dans le thread principal) afin de créer cette Form (depuis le thread principal) sauf que l'event a été envoyé d'un autre thread... et c'est bien cela qui m’embête, je ne sais pas depuis quel thread est exécuté la fonction "monClient_MessageRecu(object sender, string e)"; logiquement elle fait partie du Main(), donc du thread principal. Mais visiblement ce n'est pas dit

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

Discussions similaires

  1. CLient IRC : La form se fige
    Par Altor dans le forum Windows Forms
    Réponses: 8
    Dernier message: 17/02/2016, 18h25
  2. Réponses: 87
    Dernier message: 06/07/2011, 15h33
  3. multithreading avec windows form
    Par tortuegenie dans le forum Windows Forms
    Réponses: 9
    Dernier message: 06/06/2011, 14h23
  4. Form qui reste figée
    Par GGerald77 dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 17/09/2007, 21h13
  5. Form qui se fige lors d'un traitement malgré thread
    Par SesechXP dans le forum Windows Forms
    Réponses: 7
    Dernier message: 31/05/2007, 11h46

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