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 :

Event et control non Windows Forms


Sujet :

C#

  1. #1
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 79
    Points : 118
    Points
    118
    Par défaut Event et control non Windows Forms
    Bonjour à tous,

    J'ai créé un control (base Component) qui doit générer de temps en temps
    un Event pour informer de l'état d'avancement d'une tache. Il s'agit d'un
    message (string) mis à jour au cours du temps.
    Lorsque je place ce control sur une Form, j'ai accès au gestionnaire
    d'event pour ajouter du code dans ma Form, sans soucis.

    Problème : lorsque je souhaite mettre à jour un Label avec le message
    reçu par l'intermédiaire de l'event, j'ai un message du genre :

    Opération inter-threads non valide : le contrôle 'm_ShowLogBtn' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé.
    Je cherche à mettre à jour la propriété Text d'un Button.

    Quelqu'un a-t-il une solution à mon problème ?

    Merci par avance

    Philippe

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    135
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 135
    Points : 179
    Points
    179
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    this.BeginInvoke((Action)()=>{
    this.myLabel.Text=valeur;
    });
    (en supposant que "this" fait référence à ta form)

  3. #3
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 174
    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 174
    Points : 25 115
    Points
    25 115
    Par défaut
    si c'est un component ce n'est pas un control !

    il est impossible de modifier un control depuis un thread autre que son créateur, il faut alors demander au controle d'appeler une méthode (anonyme comme icareo le propose ou non) pour que le thread principal s'en occupe

    begininvoke est asynchrone, invoke est synchrone

  4. #4
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 79
    Points : 118
    Points
    118
    Par défaut
    merci icareo pour ta réponse. Malheureusement, je ne souhaite pas
    que le destinataire de mon control utilise PInvoke. Je souhaite copier
    le comportement d'un Timer.

    Voici des éléments supplémentaires pour la réflexion

    Code de mon control :

    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
    [Description("Component for backups"), DefaultEvent("Change")]
      public class BackupCpnt : Component
      {
     
        public class BkpCpntArgs : System.EventArgs
        {
     
          private string message;
     
          public BkpCpntArgs(string m)
          {
            this.message = m;
          }
     
          public string Message
          {
            get { return message; }
          }
        }
     
        public delegate void ChangingHandler(Object sender, BkpCpntArgs e);
     
        // event declaration 
        [Category("Configuration")]
        public event ChangingHandler Change; 
     
        ...
     
        private void OnCountingEvent()
        {
          m_LastMessage = "Counting...";
     
          // fire event
          Change(this, new BkpCpntArgs(m_LastMessage));
     
        }
    Code de la Form :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private void backupCpnt1_Change(object sender, BkpCpntArgs e)
    {
        // ça plante ici !!!
        m_ShowLogBtn.Text = e.Message;
    }

  5. #5
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 79
    Points : 118
    Points
    118
    Par défaut
    Pol63 :

    Si je change de classe de base
    de Component -> Control, ça devrait résoudre mon souci ?

  6. #6
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 174
    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 174
    Points : 25 115
    Points
    25 115
    Par défaut
    un invoke n'a rien à avoir avec un Pinvoke

    si tu veux que le destinataire n'ai pas à faire d'invoke, c'est à toi de le faire avant de déclencher ton évènement
    pour ca il y a une bidouille : system.windows.forms.application.openforms(0).invokerequired / invoke

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    135
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 135
    Points : 179
    Points
    179
    Par défaut
    Ce n'est pas un P/Invoke... c'est une exécution déportée à un autre thread.
    Et je vois mal comment tu peux faire autrement... comme le fait remarquer pol63 :

    Tu ne peux modifier l'interface utilisateur que depuis le thread STA sur lequel elle a été créée.

    Or visiblement, ta fonction "backupCpnt1_Chang" est appelée depuis un autre thread que le STA sur lequel a été créé ta form (ton thread principal, à priori).

    Donc d'une manière ou d'une autre, il va falloir dire à ton UI d'exécuter du code !

    Invoke et BeginInvoke sont là pour ça.
    Il y a d'autres moyens, mais c'est plus hardu et surtout... ça revient au même.

  8. #8
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 79
    Points : 118
    Points
    118
    Par défaut
    OK, je commence à saisir le problème.

    J'essaye de faire l'analogie avec Timer

    En regardant un peu à droite à gauche, Timer est un Component, membre
    de System.Windows.Forms. Il génère donc des event (toutes les x millisec) et
    on peut modifier un control d'une Form grace à cet event.

    Quelle propriété/caractéristique fait que cela marche avec Timer ?

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    135
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 135
    Points : 179
    Points
    179
    Par défaut
    Tu utilises System.Windows.Forms.Timer qui fait les invokes pour toi.

    Il y a une autre classe timer avec laquelle ça ne marcherait pas :

    System.Threading.Timer

    Ca a l'avantage d'être un poil plus performant... mais pas question de modifier l'UI !

  10. #10
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 174
    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 174
    Points : 25 115
    Points
    25 115
    Par défaut
    à piori il doit utiliser invokerequired et invoke, comme on te l'a conseillé ...

  11. #11
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 79
    Points : 118
    Points
    118
    Par défaut
    Ok, je vais creuser le sujet.

    Merci du coup de main !

  12. #12
    Membre régulier
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2011
    Messages : 79
    Points : 118
    Points
    118
    Par défaut
    OK, j'ai trouvé la solution.

    Effectivement, j'ai un thread lancé par mon component qui publie des event
    pour informer le component de l'avancement à l'intérieur du thread.

    Lorsque je traitais l'event du thread dans mon component, j'envoyais un event
    mais la source n'était pas le component mais le thread.
    J'ai utilisé l'astuce Application.OpenForms[0].Invoke(...) en créant un delegate
    pour une fonction qui, elle, publie l'event.

    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
    // event reçu du thread
    private void OnWaitingEvent()
        {
          Monitor.Enter(this);
          m_LastMessage = "Waiting start...";
          Monitor.Exit(this);
     
          // FireVentHandler est un delegate
          // FireEvent est un event de type FireVentHandler
          Application.OpenForms[0].Invoke(new FireVentHandler(FireEvent));
        }
     
    // publication pour l'extérieur
    private void FireEvent()
        {
          Change(this, new BkpCpntArgs(m_LastMessage, DateTime.Now));
        }
    Espère que ça servira à quelqu'un !

    Merci encore à tous !

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

Discussions similaires

  1. Comment lier user controle au windows form ?
    Par genius4evers dans le forum C#
    Réponses: 2
    Dernier message: 17/11/2011, 09h22
  2. Hosting .NET Windows Forms Controls in IE
    Par AntonioMath dans le forum Windows Forms
    Réponses: 0
    Dernier message: 21/04/2009, 21h18
  3. Login control dans Windows Forms
    Par débutant_C# dans le forum Windows Forms
    Réponses: 4
    Dernier message: 19/05/2008, 15h32
  4. [VB.NET] Type non défini quand j'appelle un Windows Form ?
    Par beegees dans le forum Windows Forms
    Réponses: 4
    Dernier message: 12/06/2006, 11h12

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