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 avec classe marshalée


Sujet :

C#

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2016
    Messages : 34
    Par défaut problème avec classe marshalée
    Bonjour,

    J'ai créer une variable dans Form1 qui utilise une structure.

    Depuis Form1, je clique sur un bouton pour ouvrir une Form2, dans laquelle je souhaite modifier la valeur de la variable de Form1 dans le constructeur.

    Mais j'obtiens le message suivant:

    ->L'accès à un membre de 'Form1.complexe' peut occasionner une exception runtime, car il s'agit d'un champ d'une classe marshalée par référence

    Je ne vois pas comment débugger.

    Merci d'avance.

    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
    namespace WindowsFormsApplication1
    {
        public struct _NombreComplexe
        {
            public double Reel;
            public double Imaginaire;
        }
     
        public partial class Form1 : Form
        {
            public _NombreComplexe complexe;
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                Form2 form = new Form2(this);
                form.Show();
            }
        }
    }
    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form2 : Form
        {
            private Form1 form1;
     
            public Form2(Form1 form)
            {
                InitializeComponent();
                form1 = form;
                form1.complexe.Reel = 1; // bug
            }
        }
    }

  2. #2
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2016
    Messages
    64
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Juin 2016
    Messages : 64
    Par défaut
    Salut,

    en théorie ton code devrait lever un warning, pas une exception

    Dans tous les cas, tu peux résoudre en principe en ça en passant par une variable locale (affecte à une variable lcoale la valeur souhaitée, puis myForm.toto = cetteVariable)
    Au passage, passe par une propriété, les champs ne sont pas censés être accédés directement (sauf constantes, etc.). Une déclaration du genre "public (type) monChamp" est à proscrire.

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2016
    Messages : 34
    Par défaut
    J'ai plus de warning, mais ma variable ne sait pas modifier ... ?

    Comment faire ?

    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public struct _NombreComplexe
            {
                public double Reel;
                public double Imaginaire;
            }
            public _NombreComplexe complexe;
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                complexe.Reel = 5;
                MessageBox.Show("Avant="+complexe.Reel.ToString());
                Form2 form = new Form2(this);
                form.ShowDialog();
                MessageBox.Show("Après=" + complexe.Reel.ToString()); // Bug: pas de modification
            }
        }
    }
    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form2 : Form
        {
            private Form1 form1;
     
            public Form2(Form1 form)
            {
                InitializeComponent();
                form1 = form;
                Form1._NombreComplexe nc = form1.complexe;
                nc.Reel = 1;
            }
        }
    }

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2016
    Messages : 34
    Par défaut
    Ca marche:

    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public struct _NombreComplexe
            {
                public double Reel;
                public double Imaginaire;
            }
            public _NombreComplexe complexe;
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                complexe.Reel = 5;
                MessageBox.Show("Avant="+complexe.Reel.ToString());
                Form2 form = new Form2(this);
                form.ShowDialog();
                MessageBox.Show("Après=" + complexe.Reel.ToString()); // Bug: pas de modification
            }
        }
    }
    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
     
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
     
    namespace WindowsFormsApplication1
    {
        public partial class Form2 : Form
        {
            private Form1 form1;
     
            public Form2(Form1 form)
            {
                InitializeComponent();
                form1 = form;
                Form1._NombreComplexe nouveau = new Form1._NombreComplexe();
                nouveau.Reel = 1;
                form1.complexe = nouveau;            
            }
        }
    }
    merci.

  5. #5
    Expert confirmé

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Je me permets d'approfondir un peu le sujet, afin d'expliquer le pourquoi ce warning à la compilation.

    La classe System.Windows.Forms.Form dérive de la classe System.MarshalByRefObject. Qu'est-ce que cela veut dire ? Et à quoi cela correspond ? En fait, c'est lié aux AppDomain (en bref, un AppDomain permet de cloisonner certaines parties d'une application, par exemple, en chargeant un plugin en provenance d'une source non sure, ou pour mettre en place un mécanisme de déchargement d'un assembly). Une application a, dès son démarrage, un AppDomain par défaut qui lui est associé. Et à moins de créer d'autres AppDomain manuellement, il n'y en aura qu'un. Et dans le cas où il n'y a qu'un seul AppDomain, cet avertissement est sans conséquence.

    Maintenant, que se passe-t-il lorsqu'il y a plusieurs AppDomain ? Chaque AppDomain est cloisonné. Un objet A dans un AppDomain AppA ne peut pas appeler une méthode directement sur un objet B dans un AppDomain AppB. Cela signifie-t-il que les AppDomain ne peuvent pas communiquer ? Non. C'est juste que la communication n'est pas direct et passe par des mécanismes de copie ou de proxy. Et c'est justement là qu'intervient la classe MarshalByRefObject. Elle précise que, pour tout classe dérivant MarshalByRefObject, il faudra utiliser un proxy pour des communications inter-domaines.

    Ainsi, reprenons notre cas de tout à l'heure : A veut appeler une méthode myMethod() de B qui est dans un autre AppDomain. Quand A réalise cet appel, il va le faire non pas sur l'objet B directement (puisque B est dans un AppDomain différent), mais sur un proxy enveloppant les appels vers B. Le proxy est en charge de réaliser le changement de contexte (on change d'AppDomain pour exécuter B.myMethod() et ensuite revenir au AppDomain initial). Ce qui sous-entend transférer les paramètres d'entrées et récupérer la valeur de sortie.

    Maintenant, que fait ton code initial ? Il accède à un attribut public d'un objet dérivant de MarshalByRefObject. Cet objet peut donc être utilisé depuis un autre AppDomain via l'utilisation d'un proxy. Or, si tu es dans un tel cas, quand tu manipules ton objet depuis un AppDomain différent, tu manipules en réalité un proxy encapsulant cet objet. Ce qui signifie que les attributs de l'objet sont définis pour l'objet, et non au niveau du proxy. D'où le risque d'exception à l'exécution (en réalité, le proxy est assez intelligent pour réussir à gérer certains accès, mais pas tous, notamment en écriture).

    Et la magie de l'utilisation des AppDomain, c'est que cette histoire de proxy est gérée automatiquement ! Le programmeur que nous sommes n'a pas à s'en occuper lui-même. Quand on récupère une instance située dans un autre AppDomain, on récupère automatiquement un objet proxy, rendant ainsi l'utilisation du proxy totalement transparente.

    Enfin, le problème ne se pose pas avec des propriétés, puisque les propriétés sont des méthodes, et sont donc proxifiées automatiquement.

    Au passage, tu auras forcément une erreur à l'exécution ici, puisque la structure _NombreComplexe n'est pas marquée comme [Serializable] (toutes les données traversant le proxy doivent l'être).

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

Discussions similaires

  1. Problème avec classe dérivé de datagrid (webForm)
    Par wadison dans le forum Framework .NET
    Réponses: 1
    Dernier message: 19/02/2008, 14h40
  2. problème avec class vector
    Par abdelmajid_daosabah dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 12/11/2007, 22h40
  3. Problème avec Class.forName
    Par steftanguy dans le forum JDBC
    Réponses: 4
    Dernier message: 14/08/2007, 16h24
  4. problème avec classe interface
    Par bandit_debutant dans le forum Langage
    Réponses: 6
    Dernier message: 05/11/2006, 20h54
  5. Problème avec classe MySQL
    Par shadeoner dans le forum Requêtes
    Réponses: 1
    Dernier message: 10/07/2006, 11h25

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