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 :

[C# 2.0][Form]Comment utiliser les Delegates & Threading [FAQ]


Sujet :

Windows Forms

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 111
    Points : 65
    Points
    65
    Par défaut [C# 2.0][Form]Comment utiliser les Delegates & Threading
    Bonjour !!

    J'ai crée une thread, qui dans sa méthode Run() appelle une autre méthode dont le but est d'updater le contenu d'un controlleur (un label), et ce chaque seconde.

    Aucun problème autour de ce qui est création de thread, ainsi que l'appel de la méthode qui se réalise bel et bien (un Console.Writeline affiche un message chaque seconde).

    Par contre, j'ai 2 problèmes :

    • 1. La thread ne modifie pas le contenu de mon controlleur comme elle le devrait, comme si elle était "séparée" de mon programme

      2. Lorsque je quitte le programme via le bouton "x" en haut à droite, ma thread continue, et reste dans les processus actifs. J'ai fait un Thread.Abort() lorsque l'on clique sur "exit" dans mon menu, mais comment en faire de même lorsqu'on clique sur le "x" (ou l'équivalent d'un ALT+F4)

    Merci d'avance

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    487
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Juillet 2002
    Messages : 487
    Points : 621
    Points
    621
    Par défaut
    1 Invoke
    2 Thread.IsBackGround
    On ne peut pas faire boire un âne qui n'a pas soif.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 111
    Points : 65
    Points
    65
    Par défaut
    Ok pour isBackground, ça marche, merci !

    Par contre pour invoke, idem que pour le post précédant
    Une petite ligne de code pour me donner un exemple

    Plus d'infos
    la classe thread :
    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
     
    using System.Threading;
     
    namespace Puiss4
    {
    	public class GameTimeThread
    	{
    		public static void run()
    		{
    			Connect4 c = new Connect4();
     
    			while (true)
    			{
    				// adds 1 to the secound counter
    				c.addSecond();			
     
    				// sleeps 1000 milliseconds ( = 1 second)
    				Thread.Sleep(1000);			
    			}			
    		}
    	}
    }
    Il semble donc que l'appel de la méthode "addSecond" située dans Connect4.cs ne soit pas correct. Que dois-je modifier dans mon code ?

    Merci d'avance

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    487
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Juillet 2002
    Messages : 487
    Points : 621
    Points
    621
    Par défaut
    Voici un exemple de code permettant la mise à jour de contrôles à partir d'un thread.
    Cet exemple suppose l'existence d'une ProgressBar et de 3 Labels sur Form1.
    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
     
    public partial class Form1 : Form
    {
       //objet timer
       System.Timers.Timer monTimer;
       //définition d'un délégué générique
       public delegate void GenericMethodInvoker<T>(T param);
     
       public Form1()
       { InitializeComponent();}
     
       private void Form1_Load(object sender, EventArgs e)
       {
          //créer un timer avec un intervale de 500ms (0,5s)
          monTimer = new System.Timers.Timer(500);
          //définir la méthode appelée à chaque déclenchement
          monTimer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
          //lancer le timer
          monTimer.Enabled = true;
       }
     
       private void Form1_FormClosing(object sender, FormClosingEventArgs e)
     {
          //arrêter le libérer le timer
          monTimer.Dispose();
          monTimer = null;
       }
     
       //cette méthode est appelée par this.monTimer dans le thread du timer
       void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
       {
          //Exemple 1
          //créer un delegué anonyme d'appel à progressBar1.PerformStep()
          MethodInvoker progressBarUpdateDelegate = delegate()
          {  this.progressBar1.PerformStep();};
          //invoque (exécute) le délegué dans le thread de création de this
          this.Invoke(progressBarUpdateDelegate);
     
          //Exemple 2
          //passage implicite du paramètre e au délégué
          MethodInvoker labelUpdateDelegate = delegate()
          { this.label1.Text = e.SignalTime.ToLongTimeString();};
     
          this.Invoke(labelUpdateDelegate);
     
          //Exemple 3
          //passage explicite d'un paramètre au délégué
          GenericMethodInvoker<DateTime> labelUpdateDelegate2 = delegate(DateTime t)
          { this.label2.Text = t.ToLongTimeString();};
          //invocation avec passage de paramètre
          this.Invoke(labelUpdateDelegate2, e.SignalTime);
     
          //Exemple 4
          //autre méthode de passage explicite d'un paramètre au délégué
          GenericMethodInvoker<String> labelUpdateDelegate3 = delegate(String text)
          { this.label3.Text = text;};
          //invocation avec passage de paramètre
          this.Invoke(labelUpdateDelegate3, e.SignalTime.ToLongTimeString());
       }
    }
    On ne peut pas faire boire un âne qui n'a pas soif.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 111
    Points : 65
    Points
    65
    Par défaut
    J'ai appliqué l'exemple à mon problème, tout se compile parfaitement, mais j'ai l'erreur suivante à l'exécution :

    Additional information: Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
    Je vois que dans l'exemple fourni, on utilise un "ElapsedEventHandler" pour le timer. Qu'en est-il à propos d'1 form ?

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    487
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Juillet 2002
    Messages : 487
    Points : 621
    Points
    621
    Par défaut
    Il faudrait voir le code qui génére l'erreur.

    La fonction ElapsedEventHandler est un exemple de fonction d'une Form appelée à partir d'un autre thread.
    Le même code s'applique si tu crée un Thread pour appeler une fonction quelconque d'une Form qui doit accéder à un contrôle de cette même Form. Peu importe le nom ou les paramètres de la fonction, la constante est le changement de thread par Invoke pour l'accès aux contrôles.
    On ne peut pas faire boire un âne qui n'a pas soif.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 111
    Points : 65
    Points
    65
    Par défaut
    Bonjour !

    Le code qui génère l'erreur est :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c.Invoke(c.delegateAddSec);
    Décidément le système de threads en C# me parait bien compliqué en Java ça m'a pris à peine 10 min pr en faire une.
    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
     
    namespace Puiss4
    	public delegate void DelegateAddSecond();
     
    	public partial class Connect4 : Form
    	{		
    	    ...
    		private Thread    gameTimeThread;	
    		public DelegateAddSecond delegateAddSec;
            ...
        }
     
    	 public Connect4()
    	 {
    		InitializeComponent();	
    		...
    		this.gameTimeThread = new Thread(new  ThreadStart(GameTimeThread.run));
    	    this.gameTimeThread.IsBackground = true;
    	    this.gameTimeThread.Name = "Game time counter";
     
    		delegateAddSec = new DelegateAddSecond(this.addSecond);	
    	}
     
        public void addSecond()
    	{	
            secElapsedLabel.Text = Convert.ToString(Convert.ToInt32(secElapsedLabel.Text) + 1);
        }

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    487
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Juillet 2002
    Messages : 487
    Points : 621
    Points
    621
    Par défaut
    Connect4 est totalement créée après la fin du constructeur. Il est donc préférable de démarrer le thread dans l'événement Connect4.Load (qui est déclenché après le constructeur) s'il doit faire appel aux méthodes de la classe.
    On ne peut pas faire boire un âne qui n'a pas soif.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    111
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 111
    Points : 65
    Points
    65
    Par défaut
    Finalement, en fouillant dans du code, j'ai trouvé une méthode plus simple... je n'utilise un delegate que pour la definition de ma thread finalement...

    J'ai placé la méthode run de ma thread dans Connect4 afin de me simplifier la tache, comme ça je travaille directement sur mes controlleurs !!

    Voilà

    Ps: un grand merci à NicolasG pour ses infos

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/09/2009, 13h15
  2. Réponses: 5
    Dernier message: 07/03/2008, 19h46
  3. [COM] Comment utiliser les événements Word ?
    Par Laurent Dardenne dans le forum API, COM et SDKs
    Réponses: 7
    Dernier message: 30/05/2004, 12h38
  4. Réponses: 11
    Dernier message: 22/12/2003, 21h06
  5. Comment utiliser les styles XP avec Dev-C++?
    Par abraxas dans le forum Dev-C++
    Réponses: 3
    Dernier message: 05/10/2003, 19h47

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