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 :

Erreur à l'arrêt d'un Thread


Sujet :

Windows Forms

  1. #1
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut Erreur à l'arrêt d'un Thread
    Bonjour a tout le monde

    J'ai crée un Thread dans mon application dont le but est
    d'afficher une boîte de dialogue modale et gérer les événements
    qui se produisent sur cette boîte de dialogue.

    Lorsque je ferme ma fenêtre principale sans arrêter le Thread,
    l'application est toujours en exécution c'est qui est d'ailleurs normal.

    Quand j'arrête le Thread par sa fonction Abort, j'ai une exception :

    [Une exception non gérée du type 'System.NullReferenceException' s'est produite dans
    system.windows.forms.dll

    Informations supplémentaires : La référence d'objet n'est pas définie à une instance d'un
    objet.]

    Je ne sais pas comment procéder pour arrêter mon Thread

    je ne sais pas si quelqu'un a déjà rencontré ce problème et comment il l'a résolu.

  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
    Salut,

    si ton thread est dans un contexte de form, invoke un Application.ExitThread sur le control ou , plus simple, si le thread n'a qu'une seule Form et a été lancé par .Run(Form), invoke un dispose sur la form, le thread se terminera tout seul (du moins retournera de .Run()).

  3. #3
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut
    Salut,

    Mon Thread est crée dans le gestionnaire de OnLoad de la fenêtre principale avec un code de ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    m_listener = new Thread (new ThreadStart(MyThreadProcedure));
    m_listener.Start();
    J'arrête enfin le thread dans OnClose() de la la fenêtre principale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    m_listener.Abort();

  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
    Je t'avoue que c'est etonnant, je viens d'essayer et ca marche correctement. Tu ne passerais pas la reference à ton thread à null avant d'appeler Abort() (ce qui est etrange c'est que l'exception est levé depuis l'assembly winform) ? On pourrait avoir un bout de code, s'il te plait ?

  5. #5
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    si tu fais tonthread.isbackground = true avant de le lancer, il s'arretera dès que le thread qui l'a démarré s'arretera
    donc plus besoin de faire abort dessus

    sinon pour ton erreur, tu dois avoir moyen de trouver quel objet est à null ...

  6. #6
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par David Fouejio Voir le message
    Bonjour a tout le monde

    J'ai crée un Thread dans mon application dont le but est
    d'afficher une boîte de dialogue modale et gérer les événements
    qui se produisent sur cette boîte de dialogue.

    Lorsque je ferme ma fenêtre principale sans arrêter le Thread,
    l'application est toujours en exécution c'est qui est d'ailleurs normal.

    Quand j'arrête le Thread par sa fonction Abort, j'ai une exception :

    [Une exception non gérée du type 'System.NullReferenceException' s'est produite dans
    system.windows.forms.dll

    Informations supplémentaires : La référence d'objet n'est pas définie à une instance d'un
    objet.]

    Je ne sais pas comment procéder pour arrêter mon Thread

    je ne sais pas si quelqu'un a déjà rencontré ce problème et comment il l'a résolu.
    Arreter un thread avec Abord déclanche ipso facto une exception mais vu ton erreur, il y a un objet qui vaut nothing (null en c#). Montre nous ton code

  7. #7
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut
    Salut à tous

    je m'excuse pour le silence, j'ai due m'absenter pour un jour.

    Comme dit Aspic, j'ai même essayé de gérer l'exception levée par Abort, mais je n'ai plus d'erreur et le programme ne s'arrête pas.

    En positionnant comme dit sperot51 IsBackground du thread à true le thread
    est bien arrêté et l'exception n'est plus levée.

    MSDN précise également que mettre un thread en arrière plan ne change pas
    les performances de ce dernier.

    Mais je pense que mon erreur est due au composant COM que j'ai inclus dans mon appli. Lorsque je l'enlève je n'ai plus d'erreur.

    J’ai aussi remarqué que lors IsBackground du thread est à false et que j’arrête le thread par Abort, le programme ne s’arrête que lorsque je clique sur l’icône (sur la barre des tâches) de la fenêtre du thread (la propriété ShowInTaskbar de ce form étant à true). comment peut on palier à cela ?

    Je vous envoi donc mon code (sans le composant COM).

    Merci à tous pour votre aide.
    Fichiers attachés Fichiers attachés

  8. #8
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    Citation Envoyé par David Fouejio Voir le message
    J’ai aussi remarqué que lors IsBackground du thread est à false et que j’arrête le thread par Abort, le programme ne s’arrête que lorsque je clique sur l’icône (sur la barre des tâches) de la fenêtre du thread (la propriété ShowInTaskbar de ce form étant à true). comment peut on palier à cela ?

    le thread principal de ton appli ne doit pas être arreté par abort à mon avis
    isbackground sert pour dire qu'un thread dépend du thread qui l'a créé
    et donc quand ce thread s'arrete, tous ceux qui en dépendent s'arrete sans broncher


    thread.abort déclenche une erreur dans le thread spécifié
    et donc normalement en cas d'erreur le thread s'arrete. il faut donc à priori avoir un try catch dans ce thread, meme s'il ne fait rien
    mais il est toutefois possible dans le catch de faire du code pour terminer proprement ce qu'on était entrain de faire
    et dans ce cas il y a aussi un truc pratique
    c'est que sur le thread principal, quand on fait thread.abort, on peut aussi attendre qu'il soit réellement terminé avec thread.join après le abort

  9. #9
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut
    Merci sperot51,

    j'appelle Abort sur le thread enfant et non sur le thread principal.

    J'ai mentionné aussi que j'ai géré l'exception levée par Abort du therad enfant.
    Je n'ai plus d'erreur mais le programme ne s'arrête pas.

    Je vais essayer le Thread.Join pour voir.

    a+

  10. #10
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    le programme ne s'arrete que si le thread principal se termine !

  11. #11
    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
    Salut David,

    Pour le Thread.Abort, je trouve ca plutot 'moche' d'arreter un thread en lui faisant lever une exception, et on peut faire autrement. Personnellement je te proposerai quelque chose comme ceci (à partir de la source ci dessus) :

    dans frmMessageMaster :

    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
     
            static frmMessageMaster frm;
            public static void Listener()
            {
                frm = new frmMessageMaster();
                Application.Run(frm);
                frm.Dispose();
            }
     
            public static void Stop()
            {
                if (frm != null && !frm.IsDisposed)
                {
                    frm.Invoke(new MethodInvoker(
                        delegate
                        {
                            Application.ExitThread();
                        }));
                }
            }
    dans frmMain :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
            private void OnLoad(object sender, System.EventArgs e)
            {
                m_mmListener.Start();
            }
     
            private void OnClose(object sender, System.EventArgs e)
            {
                frmMessageMaster.Stop();
            }
    Il faut ajouter quelques tests (nullité, deja lancé etc) mais l'idée est la. Ca evite de se prendre la tete avec des catchers d'exception, et ca ferme proprement le thread de la fenetre secondaire (qu'il soit back ou foreground).

  12. #12
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    à mon avis tu es un petit peu trop utopiste
    et puis c'est pas son thread principal qu'il veut arreter
    et un thread n'a rien à voir avec un form

  13. #13
    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 sperot51 Voir le message
    à mon avis tu es un petit peu trop utopiste
    et puis c'est pas son thread principal qu'il veut arreter
    et un thread n'a rien à voir avec un form
    heu, je ne touche pas au thread principal ici, je retourne juste de l'application.Run de la deuxieme form, ce qui disposera cette deuxieme form et terminera le thread créé pour l'occasion. Tu peux appeller frmMessageMaster.Stop() ou tu veux ca ne terminera que le thread de la form secondaire, sans consequence pour le thread appellant.

    J'entends bien qu'un thread n'a rien a voir avec une form, mais ici, on a thread de presentation qui a créé une form, donc dans une logique de presentation, tu peux raisonnablement invoker ce thread, pour lui demander de se detruire lui meme dans son context (ce qui est le cas ici). Tu ne couperas pas l'operation en cours, contrairement à une levée d'exception qui t'arretera net l'operation en cours.

    Utopiste, surement, mais quand on peut faire (un peu plus, du moins) propre pourquoi s'en priver. =)

  14. #14
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    ah oui t'as ptete raison, pas tout vu encore là dessus ...

  15. #15
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut
    Salut SirJulio,

    Merci pour ta proposition.

    Je vais tester ca. La seule chose que je ne comprend pas c'est le
    delegate
    Pourquoi appeler Application.ExitThread par un delegate et pas directement ?
    puisque l'appel de cette fonction arrête le thread en cours (ici le thread enfant).
    d'autre part est ce que la déclaration de frm ne doit pas être private :

    private static frmMessageMaster frm;

    ?

    Salut sperot51,
    Jai essayé le Thread.Join. Il bloque effectivement le thread principal mais ne l'arrête pas tant que je n'ai pas cliqué sur l’icône (sur la barre des tâches) de la fenêtre du thread enfant.

  16. #16
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 177
    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 177
    Points : 25 125
    Points
    25 125
    Par défaut
    comment démarres tu le thread ?

  17. #17
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut
    j'ai donné le code source
    tu peux y jeter un coup d'oeil.

  18. #18
    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
    Salut David,

    en fait si tu appelles Application.ExitThread() directement tu vas arreter le thread qui a fait l'appel (donc le thread de ta premiere fenetre ici) ce qui n'est apparement pas l'effet attendu. Dans 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
    static frmMessageMaster frm;
            public static void Listener()
            {
                frm = new frmMessageMaster();
                Application.Run(frm);
                frm.Dispose();
            }
     
            public static void Stop()
            {
                if (frm != null && !frm.IsDisposed)
                {
                    frm.Invoke(new MethodInvoker(
                        delegate
                        {
                            Application.ExitThread();
                        }));
                }
            }
    j'aurai pu explicitement mettre "static frmMessageMaster frm;" en private mais ca revient au meme (class = private par defaut). Pour l'invoke, j'aurais pu rajouter un test if (this.InvokeRequired) aussi, Stop() etant public je mise sur le fait qu'il soit appellé par un thread tiers mais on peut rajouter la ligne. Stop() pouvant etre appelé par n'importe quel thread on doit s'assurer qu'il est bien passer au thread concerné.

    Pour le delegate, tu ne comprends ce qu'est un delegate ici ou bien son role ? dans le deuxieme cas, c'est juste pour marshallé un Application.ExitThread par une methode anonyme (je sais c'est mal !) sur le thread de la fenetre secondaire à son prochain ilde.

  19. #19
    Membre régulier
    Inscrit en
    Janvier 2006
    Messages
    165
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 165
    Points : 106
    Points
    106
    Par défaut
    Salut SirJulio,

    MethodInvoker est déjà un delegate et ca marche aussi bien comme suit :

    frm.Invoke(new MethodInvoker(Application.ExitThread));

    Qu'elle est la différence entre ces deux intructions ?

    Application.Run(frm);
    et
    frm.ShowDialog();

    j'ai constaté que la 1ère forme résoud certain problèmes que je recontrais

  20. #20
    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 David Fouejio Voir le message
    Salut SirJulio,

    MethodInvoker est déjà un delegate et ca marche aussi bien comme suit :

    frm.Invoke(new MethodInvoker(Application.ExitThread));
    Salut

    Ha oui tiens, my bad, j'avais jamais pensé à ca. En effet, c'est tout à fait correct, tellement l'habitude des delegate (anonyme) que j'en oublie qu'on peut faire ca.

    La difference pratique se situe au niveau de la fermeture, quand tu lances un showdialog et qu'il retourne (click sur la croix) la fenetre est simplement hider, DialogResult est passé à cancel, et elle n'est pas disposée, à l'inverse quand tu appelles Application.Run(Form), avant le retour de cette methode, le dispose de ta form sera appellé sur le ExitThread (que tu l'appelles ou non, car le fait de clicker sur la croix l'appelle implicitement).

    C'est à ma connaissance, la seule difference d'un point de vue technique, mais en dehors de ces considerations, utiliser un Application.Run, sur chaque premiere fenetre affichée par un thread est une bonne habitude, du moins meilleur que showdialog() ne lancant une pompe à message que par neccessité. De plus, Application.Run() ne fait que lancer une loop, sans se soucier du reste (raccourci bien entendu), alors que ShowDialog, de part son usage, s'assure de freezer le context appelant si besoin (et le defreezer en sortie), donc Application.Run() est bien plus optimisé dans ton cas.

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

Discussions similaires

  1. [XL-2007] Erreur qui arrête (stop) excel
    Par fartouk dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 11/05/2010, 06h13
  2. [WS 2003] Erreurs d'arrêt bizarre Windows 2003 Server !
    Par sofien dans le forum Windows Serveur
    Réponses: 1
    Dernier message: 15/05/2009, 16h59
  3. Erreur de segmentation dans un thread
    Par Littlepea dans le forum wxWidgets
    Réponses: 3
    Dernier message: 27/06/2008, 20h18
  4. [XPATH] Erreur XPath sur du multi-thread
    Par pvoncken dans le forum Format d'échange (XML, JSON...)
    Réponses: 2
    Dernier message: 08/02/2006, 16h19
  5. [threading][logging] erreur de loggage dans un thread
    Par Guigui_ dans le forum Général Python
    Réponses: 5
    Dernier message: 12/10/2005, 16h01

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