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 :

Fenetre.show() apparaît puis disparait


Sujet :

Windows Forms

  1. #1
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut Fenetre.show() apparaît puis disparait
    Salut , je réalise en ce moment un petit software de messagerie instantanée et j'ai un petit soucis que je vais essayer de vous exposer.

    j'ai donc une classe server.cs qui écoute les connections entrantes

    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
    public void run()
            {       
                while (true)
                {
                    try
                    {
                        Socket clientSocket = sockeServ.Accept();
                        ThreadContact tc = new ThreadContact(clientSocket);
                        tc.messageEvent += new      ThreadContact.MessageEventHandler(tc_messageEvent);
                        Thread caller = new Thread(new ThreadStart(tc.run));
                        caller.Start();
                    }
                    catch(SocketException s)
                    {
     
                    }
                }
            }
            public void tc_messageEvent(object sender, MessageArrivedEvent e)
            {
                if (e != null) messageEvent(this, e);
     
            }
    Ensuite j'ai une classe threadContact qui récupere les messages entrant, toujours dans un thread pour ne pas bloquer les autres connections entrantes.

    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
     
    public void run()
            {
     
               // NetworkStream ns = new NetworkStream(socket);
     
                 byte[] bytes = new byte[256];
     
                // Get reply from the server.
                 socket.Receive(bytes);
                 MessageArrivedEvent e = new MessageArrivedEvent(Encoding.UTF8.GetString(bytes),socket);
                 if (e != null)
                 {
                     messageEvent(this, e);
                 }
            }
    Donc en gros, sur les deux bouts de code précédents, lorsqu'une personne se connecte à moi, je lance un autre Thread (ThreadContact) pour récuperer les messages, et ensuite, forcément, j'utilise le système d'évènements-delegate pour renvoyer ce message à ma classe carnet, ceci explique cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     if (e != null)
                 {
                     messageEvent(this, e);
                 }
    bref je pense que vous avez capté, y a rien d'extraordinaire.

    Donc maintenant d'un point de vue fonctionnel, une fois que j'ai récupéré ce foutu message dans ThreadContact, je dois le renvoyer à ma classe carnet grâce aux évènements ( ce que je réussis à faire), et il me reste à vérifier, une chose:

    LA fenêtre de conversation est-elle déjà ouverte???????

    et bien vous l'aurez deviner, dans le cas que je chercher à gerer elle n'est pas ouverte.
    Donc voici un extrait de mon code Carnet.cs pas très complexe:

    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
    public void tc_messageEvent(object sender, MessageArrivedEvent e)
            {
                if (e != null)
                {
                    MessageBox.Show("coucou" + e.EventText);
                    openOrFocusWindow(e);
                }
            }
    public void openOrFocusWindow(string msg)
    {
    //si fenetre pas encore ouverte
    if (instanceFenetreDejaOuverte==null)
                {
                    //si fenetre non encore ouverte
                     ctArrivant = new Contact();
                     ctArrivant.Pseudo = pseudoEm;
                     ctArrivant.Id = idContactEm;
     
                    //Ouverture d'une nouvelle fenêtre de conversation
                    Fenetre fn = new Fenetre(ContactConnect, ctArrivant, so);
                    fn.Carnet = this;
                    fn.showMsg.AppendText(ctArrivant.Pseudo + " a dit: " + messageFromXml);
                    fn.showMsg.AppendText("\n");
                    fn.Text = "Vous conversez avec : " + ctArrivant.Pseudo;
                    LesConversationsEnCours.Add(fn);
                    fn.Show();
                    fn.Focus();
                }
    }
    voilà dans dans le bout de code ci-dessus je récupère donc mon évènement, et j'appelle openOrFocusWindow(msg)

    et donc là je vois que ma fenêtre n'est pas encore ouverte, donc bon, j'en crée une nouvelle et je fais un fen.Show().

    Et bien, en mode debug je constate donc que la fenêtre s'ouvre bien pendant un instant, mais pas complètement, c'est-à dire que c'est tout blanc à l'intérieur , puis, ensuite lorsque je reviens dans la méthode run de ThreadContact, précisément ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     if (e != null)
                 {
                     messageEvent(this, e);
                 }
    et bien apres l'avoir appellé elle disparait, snif!!!


    Cependant si je fais un ShowDialog() au lieu d'un Show(), ça marche mais ce n'est pas ce que je souhaite.

    Voilà si quelqu'un à une idée, n'hésitez pas car c'est un vrai casse tête

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Bonjour mnemonic78,

    c'est normal, Show() n'est pas bloquant, ShowDialog() l'est car il incorpore sa propre pompe à message. Pour que ton show marche correctement, il faut lancer une boucle de message sur le thread qui à créer la fenetre (ton thread de reception ici), en faisant un appel à Application.Run(fn).

    Bon courage.

  3. #3
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    ok donc d'après toi au lieu de mettre Show(), j'ai juste à remplacer par Application.Run(fn)?


    Sinon j'ai une autre petite question?

    Que se passe t-il si je ferme une form ouverte avec un showDialog, un Show() ou ici avec un Run()???

    En debug, j'ai remarqué que mes fenêtres de discussion qui pour chacune incorpore un thread d'écoute, continuent à écouter même si elles ont été fermé, c'est assez problématique une fenêtre fermé, donc, qui n'est plus visible, mais qui vit encore!! Puisque à chaque fois je suis obligé de recréer un handle (handleCreate). Mais cependant, certaine fois, quand j'attend un moment, on m'affiche quand je veux creer le handle de la fenetre qui n'est plus visible, que je ne peux atteindre un objet supprimé.
    En conséquence j'en conclue que l'objet vit encore pendant un moment et est ensuite détruit, cela est encore plus problématique. Pourrais-tu m'éclairer sur ce point??

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Quand tu clos une fenetre ouverte avec Run() ou Show() (donc une fenetre non modale), la fenetre sera disposée à sa fermeture, a contrario avec ShowDialog, elle ne l'est pas. Reafficher une fenetre disposée peut etre problematique. Le probleme de Show(), c'est que in fine, cela revient à faire Visible = true;, dans un contexte ou le thread appelant est deja pris dans une boucle, ca fait ce que l'on attend, mais si ce thread n'a pas de pompes à message, ca va afficher la fenetre un cour instant, mais le thread ne s'arretant pas pour traiter les messages, la fenetre va freezer ou devenir blanche, car le thread va se terminer, tu as un handle dans le vide que personne ne traite. Donc oui, des qu'on veut afficher une fenetre sur un thread, il faut s'assurer que Run ait été appelé au moins une fois, pour créer le contexte evenementiel.

    Il faut t'assurer qu'au moment du Dispose, ta fenetre va fermer toutes les ressources qu'elle aurait utilisé (pour eviter les problematiques de thread d'ecoutes survivants). Pour cela abonne toi à l'event Disposed de form, et gere la fermeture de ton ecoute.

    Bref, la destruction des objets ont en a rien à faire en .Net (la destruction dans l'absolu, c'est du release de memoire, ce n'est pas notre probleme), l'important est que tu puisses controler que ta form relache bien ton thread, et c'est la qu'il faut intervenir sur l'event Disposed pour stopper ce thread. L'objet va survivre, mais au moins les ressources hypothetiquement acquise ne t'embeteront pas.

    En esperant t'avoir aidé.

  5. #5
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    En mettant un Application.Run(fn) il me dit que le démarrage d'une deuxieme boucle de message sur un seul thread n'est pas valide!!!

    Je suis un peu perdu là, moi si j'utilise des Show() et non des ShowDialog () à la base, c'est pour que l'utilisateur puisse naviguer de fenêtre en fenêtre.

    qu'est-ce que l'event dispose ? quand-est-ce qu'il se déclenche?
    Disons que je m'abonne à l'event dispose et que dans cette méthode j'arrête le thread d'écoute. Le gars connecté à moi , m'enverra, alors des messages dans le vide puisque je n'écouterai plus sur la socket, le thread d'écoute sur celle-ci étant définitivement stoppé.

    Donc, je me dis, au lieu de fermer la fenêtre, lorsque l'utilisateur clique sur la croix, ne vaudrait-il pas mieux juste la cacher??? ne serait-ce pas plus simple comme fonctionnement et est ce que c'est possible en m'abonnant à l'event close(), de lui interdire de fermer la fenêtre mais de la cacher?? L'utilisateur croira qu'il l'a fermer , alors qu'en réalité elle est simplement cachée.
    Comme ça plus de problèmes de thread, ensuite j'aurai plus qu'a stocker toutes mes fenêtres cachées dans une liste et j'ai juste à les montrer quand l'utilisateur le souhaite.

  6. #6
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    Bon et bien après plusieurs heures de recherche sur des forums surtout anglais, j'ai l'impression que cette question de l'affichage de form avec la méthode Show() dans un thread est vraiment impossible et ça me fait vraiment Chxxx, c'est incroyable !! je vais être obligé d'utiliser ce fichu showDialog()!!.

  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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void ShowUneFenêtreDansUnAutreThread ()
    {
      MethodInvoker m = new MethodInvoker(delegate{
        Form1 f = new Form1();
        f.ShowDialog();
      });
      m.BeginInvoke();
    }

  8. #8
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    Avec showDialog() ma fenêtre ne disparaît pas.
    Mais malheureusement je ne veux pas utiliser showDialog() maisplutôt la fonction Show()

  9. #9
    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
    Essayes tu véra

  10. #10
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    ben avec showDialog ué ça marche je suis tout a fait d'accord mais c'est mieux d'utiliser Show pour pouvoir se déplacer de fenêtre en fenêtre.
    je vais tester ton code en mettant Show() qui sait ca peut peu-être fonctionner!

  11. #11
    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
    Faut toujours que ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    private void button1_Click(object sender, EventArgs e)
            {
                    Form1 f = new Form1();
                    f.ShowDialog();
            }
    Là t'as une seule fenêtre à la fois, ça bloque

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    private void button1_Click(object sender, EventArgs e)
            {
                MethodInvoker m = new MethodInvoker(delegate
                {
                    Form1 f = new Form1();
                    f.ShowDialog();
                });
                m.BeginInvoke(null, null);
            }
    Là la deuxième fenêtre est affichée et on peut toujours revenir à la première sans problème. Bien sur tout est fermé si on ferme la fenêtre principale ...

  12. #12
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    ok ok ben merci beaucu, jvais tester ça, par contre on close de la fenêtre avec un Show() d'après ce que j'ai entendu le dispose se fait tout seul, tandis qu'avec ShowDialog() on doit le faire nous même non?

  13. #13
    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
    Mais si ça te dérange tant que ça, utilises un using :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    private void button1_Click(object sender, EventArgs e)
            {
                MethodInvoker m = new MethodInvoker(delegate
                {
                    using(Form1 f = new Form1())
                    {
                       f.ShowDialog();
                    } /* f est automatiquement disposé, quoiqu'il arrive entre les deux accolades */
                });
                m.BeginInvoke(null, null);
            }

  14. #14
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    disposé ça veut bien dire que l'objet form va être supprimer lors de la fermeture de la fenêtre?

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Heu, je n'ai aucun probleme avec ce 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
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                Thread t = new Thread((ThreadStart)
                    delegate
                    {
                        Form1 f = new Form1();
                        Application.Run(f);
                    });
                t.SetApartmentState(ApartmentState.STA);
                t.Start();
     
            }
        }
    Si le runtime te sort que Run() ne peut etre appelé qu'une fois, c'est que tu l'as deja appelé, et dans ce cas Show() suffit.

  16. #16
    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 mnemonic78 Voir le message
    disposé ça veut bien dire que l'objet form va être supprimer lors de la fermeture de la fenêtre?
    Oui

    Citation Envoyé par SirJulio Voir le message
    Si le runtime te sort que Run() ne peut etre appelé qu'une fois, c'est que tu l'as deja appelé, et dans ce cas Show() suffit.
    ça sert à rien de créer un nouveau thread et de faire juste Show. La fonction Show n'attend pas que la fenêtre soit fermée pour continuer l'exécution ... qui mène vers la fin du thread, donc le thread est killé avec la fenêtre dedans. Et utiliser plusieurs fois Application.Run, bof ...

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Citation Envoyé par smyley Voir le message
    ça sert à rien de créer un nouveau thread et de faire juste Show. La fonction Show n'attend pas que la fenêtre soit fermée pour continuer l'exécution ... qui mène vers la fin du thread, donc le thread est killé avec la fenêtre dedans. Et utiliser plusieurs fois Application.Run, bof ...
    Bah je te dirais que je suis le premier à penser que gerer des fenetres sur plusieurs threads distincts, c'est AMHA, pas une bonne idée. Je verrai plus un seule thread de presentation qui se fait invoquer par les threads clients, c'est propre, central et "logique" (j'entends pas de fenetre qui se ballade un peu partout).

    Mais de toutes facons, pour faire proprement une boucle evenementiel en C# sur un thread nouvellement créé (ceci etant valable aussi bien sur le principal que sur d'hypothetique thread tiers), c'est soit Run(), soit ShowDialog() (c'est moche AMHA, mais ca fait le job, donc bon).

  18. #18
    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 SirJulio Voir le message
    Bah je te dirais que je suis le premier à penser que gerer des fenetres sur plusieurs threads distincts, c'est AMHA, pas une bonne idée. Je verrai plus un seule thread de presentation qui se fait invoquer par les threads clients, c'est propre, central et "logique" (j'entends pas de fenetre qui se ballade un peu partout).
    Je te dit pas que c'est mal de tout gérer dans un thread, et d'ailleurs je trouve que le mieux c'est de toujours avoir une trace des fenêtres ouvertes. Ensuite un simple Show et ça marche, tant que cette fenêtre ne se fait pas disposer et autres choses semblables. (Cette centralisation n'est pas toujours réalisable sur un gros projet).

    C'est simplement que je suis arrivé, j'ai vu un roman, et j'ai vu quelqu'un qui voulais absolument pouvoir afficher une fenêtre avec Show et pour laquelle elle semble se faire détruire un peut plus loin. En plus là c'est un programme de messagerie instantanée et dès le départ il y a plusieurs threads (d'après ce que je vois dans le premier message) dont l'histoire de tout centraliser n'est plus valable (et je ne pense pas que ce soit efficace pour une messagerie instantanée ...).
    Alors le moyen le plus simple d'avoir une fenêtre "presque" modale qui reste affichée indéfiniment est de lui créer son propre thread (via BeginInvoke) et d'y afficher la fenêtre de manière bloquante, mais sur son propre Thread.

    So, voilà comment je vois la chose...

  19. #19
    Membre du Club
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 45
    Points
    45
    Par défaut
    ok merci les gars pour toutes ces précisions sur le sujet!!

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

Discussions similaires

  1. fenetre de connexion, puis rien
    Par Celano dans le forum Administration système
    Réponses: 1
    Dernier message: 01/06/2015, 17h29
  2. [DOM] Le texte apparait puis disparait
    Par Nasky dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 08/06/2007, 14h38
  3. Réponses: 10
    Dernier message: 03/11/2006, 18h39
  4. Réponses: 4
    Dernier message: 30/08/2005, 12h59

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