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 :

Problème thread pointeur non instancié


Sujet :

C#

  1. #1
    Membre habitué
    Inscrit en
    Juin 2007
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 359
    Points : 153
    Points
    153
    Par défaut Problème thread pointeur non instancié
    Bonjour, je voudrais comprendre pourquoi ce petit bout de code ne marche pas:
    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
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
     
    namespace Test_appli_graph
    {
        public partial class Form2 : Form
        {
            Form1 aForm;
            public Form2()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                Thread my_Thread;
                my_Thread= new Thread(new ThreadStart(Traitement));
                my_Thread.Start();
                Thread.Sleep(3000);
                aForm.Dodo();
            }
            private void Traitement()
            {
                Application.Run(aForm=new Form1());
            }
        }
    }
    En effet, lorsque je tente de faire aForm.Dodo();
    Il me lève une exception selon laquelle aForm n'est pas instancié, alors que je l'instancie dans mon Thread.start();,
    Et là je comprends pas ce qui bug,...

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Euh... a priori si ton bouton est dans une Form, tu es déjà dans la boucle principale de l'application (Application.Run, qui est appelé dans le Main de Program.cs en général). Donc là tu cherches à relancer la boucle principale de l'appli dans un nouveau thread, et je pense que les effets sont plus ou moins imprévisibles...
    D'ailleurs je ne comprends pas bien ce que tu cherches à faire là...

  3. #3
    Membre habitué
    Inscrit en
    Juin 2007
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 359
    Points : 153
    Points
    153
    Par défaut
    Bha, je cherche simplement à ouvrir une form dans un thread indépendant du premier,...
    Mais, je ne comprends pas pourquoi il me lève un NullHandlerException,...
    Alors que pour moi ma form1 est instancié,...
    Mais bon, j'ai enlevé le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Application.Run(aForm=new Form1())
    et l'ai remplacé par Mais il n'y a eu aucune différence,...

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    et pourquoi pas tout simplement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
            private void Traitement()
            {
                aForm=new Form1();
                aForm.Show();
            }

  5. #5
    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 tomlev Voir le message
    Euh... a priori si ton bouton est dans une Form, tu es déjà dans la boucle principale de l'application (Application.Run, qui est appelé dans le Main de Program.cs en général). Donc là tu cherches à relancer la boucle principale de l'appli dans un nouveau thread, et je pense que les effets sont plus ou moins imprévisibles...
    D'ailleurs je ne comprends pas bien ce que tu cherches à faire là...
    Salut,

    non, non, c'est bien la bonne methode. Application.Run() lancant une boucle sur le thread courant, c'est tout à fait correct, tu auras deux threads ayant chacun leur loop.

    @L'op : le code marche tres bien (aucune exception), cependant tu devrais eviter de sleeper le thread de Form2 (la form2 va se freezer pendant 3 secs, c'est moche !) et avant de lancer le second mettre son appartment en STA (comme pour la premiere avec [STAThread]), comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                Thread my_Thread;
                my_Thread = new Thread(new ThreadStart(Traitement));
                my_Thread.SetApartmentState(ApartmentState.STA);
                my_Thread.Start();
    il nous manque aussi le aForm.Dodo(), c'est peut etre lui qui te leve quelque chose.

    Edit : @Tomlev :

    si tu fais simplement un Show(), la form se lancera et se fermera immediatement ( son thread se terminant par la meme). Si un thread n'a pas de loop, il faut lancer la premiere form de ce thread avec Application.Run(), une fois fait une fois et tant que tu n'appelles pas Application.ExitThread(), les autres forms peuvent etre lancées par un Show() (la boucle existant deja sur le thread).

  6. #6
    Membre habitué
    Inscrit en
    Juin 2007
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 359
    Points : 153
    Points
    153
    Par défaut
    SirJulio !!!
    Je dois avouer que j'espérais que tu répondes,...
    Bon voilà, mon problème vient bien de mon aForm.Dodo() dont voilà le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public void Dodo()
            {
                Thread.Sleep(3000);
                myPlayer.Stop();
                pictureBox1.Image = (Bitmap)Properties.Resources.Image2;
                this.Refresh();
            }
    Mais, je ne pense pas que le problème vienne de là, parceque j'ai une exception de type NullReferenceException, à l'appel de la fonction aForm.Dodo();
    Mais mon code ne marche pas,...
    En tout les cas pas chez moi, j'essaie ce que tu as mis,...

    PS: ça y est c'est essayé, mais ça ne fait aucune différence,...
    Je pense que le problème vient du fait que le thread my_Thread n'ait pas eu le temps d'implémenter le Form1 aForm, en tous cas, c'est tout ce que je vois,...
    Surtout que, le temps que j'observe l'exception, la form aForm apparait, mais l'exception reste tout de même,...

  7. #7
    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 tu as enlevé le Sleep(), il se peut qu'en effet tu appelles Dodo() sur une reference qui n'a pas encore été créé (c'est long à partir un thread). J'ai essayé avec le code ci dessous et ca fonctionne.


    Pour la form avec le button de creation :
    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
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    using WindowsFormsApplication1;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form2 : Form
        {
            Form1 aForm;
            AutoResetEvent eve;
            static object syncObj = new object();
     
            public Form2()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                //On deporte la creation du thread dans un autre thread (!)
                ThreadPool.QueueUserWorkItem(delegate
                {
                    lock (syncObj)
                    {
                        //Un event qui passera à true quand aForm sera effectivement affiché
                        eve = new AutoResetEvent(false);
                        //On créé et start le thread ...
                        Thread my_Thread;
                        my_Thread = new Thread(new ThreadStart(Traitement));
                        my_Thread.SetApartmentState(ApartmentState.STA);
                        my_Thread.Start();
                        //
                        // ... et on attend que la fenetre soit effectivement construite
                        eve.WaitOne();
                        //ensuite on appelle notre methode en l'invoquant (on est ni sur le thread de la Form2, ni sur celui de l'aForm)
                        aForm.Invoke(new MethodInvoker(aForm.Dodo));
                    }
                });
     
                string result = string.Format(@"L'id du thread de cette Form est : {0}
    Ce thread possede une boucle de message : {1}", Thread.CurrentThread.ManagedThreadId, Application.MessageLoop);
                Label lbl = new Label();
                lbl.AutoSize = true;
                lbl.Text = result;
                lbl.Location = new Point(20, 20);
                this.Controls.Add(lbl);
            }
            private void Traitement()
            {
                aForm = new Form1();
                //On inscrit une method sur Load pour passé l'autoresetevent à true au chargement
                aForm.Load += new EventHandler(aForm_Load);
                //et on lance la nouvelle Form
                Application.Run(aForm);
            }
     
            void aForm_Load(object sender, EventArgs e)
            {
                //On signale ...
                eve.Set();
                //on nettoie ...
                eve.Close();
                //on desinscrit
                aForm.Load -= aForm_Load;
            }
     
        }
    }
    Pour la form a creer :
    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
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
     
            public void Dodo()
            {
                Label lbl = new Label();
                lbl.AutoSize = true;
                string result = string.Format(@"L'id du thread de cette Form est : {0}
    Ce thread possede une boucle de message : {1}", Thread.CurrentThread.ManagedThreadId, Application.MessageLoop);
                lbl.Text = result;
                lbl.Location = new Point(20, 20);
                this.Controls.Add(lbl);
            }
        }
    }
    Pour une rapide explication, je remplace le Sleep() sur le thread de creation par un AutoResetEvent que je signalerai dans le Load de la form à créer. A noter aussi, que je ne me sers pas du thread de ma form, c'est plus pour le principe, je me sers du ThreadPool pour l'operation, comme ca mes threads d'affichage ne sont jamais retenu (par des sleeps ou autres).

    Normalement ca correspond a ce que tu cherches, mais dans tous les cas, evite à tout prix d'endormir un thread d'affichage, c'est extremement frustrant quand la form ne repond plus et se fige, et on peut, somme toute, souvent trouvé d'autres solutions.

    Bon courage. =)

  8. #8
    Membre habitué
    Inscrit en
    Juin 2007
    Messages
    359
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 359
    Points : 153
    Points
    153
    Par défaut
    OK, merci, j'essaye ça de suite !

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Ouah, le code est tout de suite plus compliqué à comprendre
    Mais ça me semble quand-même bizarre que son code initial ne marchait pas... avec un Sleep de 3 secondes, la 2e Form aurait du avoir largement le temps de de se créer, non ?

  10. #10
    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 tomlev Voir le message
    Ouah, le code est tout de suite plus compliqué à comprendre
    Mais ça me semble quand-même bizarre que son code initial ne marchait pas... avec un Sleep de 3 secondes, la 2e Form aurait du avoir largement le temps de de se créer, non ?
    Ben ca m'etonnait aussi, pour ma part, en prenant le code de l'Op, ca marchait tres bien (c'est pour ca que je demandais si n'y avait pas un probleme avec la methode Dodo()), mais bon dans tous les cas, il n'utilisera plus de sleep sur un thread d'affichage, et c'est deja pas mal. =p

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/05/2012, 08h37
  2. problème thread : pointeurs de fonctions
    Par tech_77 dans le forum POSIX
    Réponses: 2
    Dernier message: 02/12/2010, 12h59
  3. Problème de pointeur sur plusieurs threads
    Par Schpitt dans le forum Threads & Processus
    Réponses: 4
    Dernier message: 01/09/2010, 19h56
  4. TBitmap et problèmes de pointeurs...
    Par benj63 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/07/2003, 13h39
  5. [Accents - XML] Problème de codage non supporté !!
    Par Smortex dans le forum Composants VCL
    Réponses: 6
    Dernier message: 24/11/2002, 11h00

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