[C#][ActiveX][Thread][HTML/Javascript] Evénements OK mais pas dans tous les cas

Mediant Messages postés 2 Date d'inscription mercredi 20 février 2008 Statut Membre Dernière intervention 17 mars 2008 - 17 mars 2008 à 15:44
Mediant Messages postés 2 Date d'inscription mercredi 20 février 2008 Statut Membre Dernière intervention 17 mars 2008 - 17 mars 2008 à 20:31
Bonjour !

Voilà, j'au dû me mettre au C# il y a quelque jours afin de réaliser un composant ActiveX.

J'ai besoin que ce composant puisse m'envoyer des événements pouvant être "captés" depuis la page HTML qui l'utilisera.

Après avoir passer pas mal de temps à chercher de la doc sur la création d'activeX en C# et sur la gestion d'événements, jai pu arrivé à une solution (:aie:).

Lorsque j'appelle une méthode de mon objet intégré dans la page, cela lance bien un événement et arrive à bien être capté dans lapage HTML.

Mais pour les besoins que j'ai, ces évenements devront être lancés par un thread réalisant une tâche dépendante.

Et c'est là que le problème intervient. Lorsque depuis le thread, je fais appel la méthode de "l'objet parent" (si vous me permettez l'expression) cela me lève une Exception bien spécifique .. alors que cela fonctionne lorsqu'elle est appelée directement via la page HTML ??

Ainsi, pour les besoins de l'explication, j'ai tenté de vous proposer une version "light" de mon problème. Le composant repose sur un TextBox qui me permet de "tracer" différents messages.

Voici la page HTML qui intègre le composant :

<html>
    <head><title>ActiveXSourcingAutre</title>
<script language= "javascript">

function FoncActiveThreadJs() {
    if(monObj){
        monObj.FoncActiveThread('CHAPI','CHAPO');
    }
    else alert('JS: FoncActiveThreadJs() : monObj non disponible');
}

function demLance() {
    if(monObj){
        monObj.demandeLance();
    }
    else alert('JS: demLance() : monObj non disponible');
}
</script>
    </head>
    
       <object id="monObj" classid="activex/ActiveXSourcingAutre.dll#ActiveXSourcingAutre.MyWindowControlAutre"></object>
       <script LANGUAGE="JavaScript" for="monObj" event="ClickEventThread(a,b)">
            alert("Evenement capte avec ["+a+"]["+b+"]");
       </script>

[javascript: FoncActiveThreadJs(); FoncActiveThreadJs]

[javascript: demLance(); demLance]
    
</html>


et le code C# associé

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

namespace ActiveXSourcingAutre {
    public delegate void ClickEventHandlerThread(string a, string b);

    [System.Runtime.InteropServices.GuidAttribute("9621A92C-3FBD-4be4-9153-51EEC1444507")]

    [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)]
    public interface ControlEventsAutre
    {
        [System.Runtime.InteropServices.DispIdAttribute(0x60035000)]
        void ClickEventThread(string a, string b);
    }

    [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)]
    public interface MonInterfaceAutre {
        [System.Runtime.InteropServices.DispIdAttribute(0x60060003)]
        void demandeLance();
        [System.Runtime.InteropServices.DispIdAttribute(0x60060007)]
        void FoncActiveThread(string a, string b);
    }

    public class MonThreadHandle {

        MyWindowControlAutre mxcparent;

        public MonThreadHandle(MyWindowControlAutre mxcparam) {
            this.mxcparent = mxcparam;
        }

        public void AffichageInterp() {
            mxcparent.FoncActiveThread("JOJO", "JUJU");
        }

        public void ThreadLoop() {
            // .... Réalise différents traitements (attente de lectures asynchrones notamment ..)
            // et dans un cas particulier fait appel à la fonction suivante
            AffichageInterp();
        }
    }

    [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None), System.Runtime.InteropServices.ComSourceInterfaces(typeof(ControlEventsAutre))]
    public class MyWindowControlAutre : System.Windows.Forms.UserControl, MonInterfaceAutre //, ComInteropControlInterface
    {
        System.Windows.Forms.TextBox tx = new TextBox();

        MonThreadHandle threadHandle;
        Thread t;

        event ActiveXSourcingAutre.ClickEventHandlerThread ClickEventThread;

        private void InitializeComponent() {
            this.Name = "MyWindowControlAutre";
        }

        public MyWindowControlAutre()
            : base() {
            initMyWindowControlAutre();
        }

        private void initMyWindowControlAutre() {
            tx.Text = "";
            Size = new System.Drawing.Size(700, 450);
            tx.Size = this.Size;
            tx.Multiline = true;
            tx.ScrollBars = ScrollBars.Vertical;
            tx.AcceptsReturn = true;
            tx.AcceptsTab = true;
            tx.WordWrap = true;
            this.Controls.Add(tx);
        }

        public void demandeLance() {
            Lance();
        }

        //[STAThread]
        void Lance() {
            threadHandle = null;
            t = null;
            try {
                threadHandle = new MonThreadHandle(this);
                t = new Thread(new ThreadStart(threadHandle.ThreadLoop));
                t.Start();                
            }
            catch {
                traceFen("Thead non lance");
                return;
            }
        }

        public void FoncActiveThread(string a, string b) {
            traceFen("Etape A : FoncActiveThread :: a=" + a + " b=" + b);
            ClickEventThread = new ClickEventHandlerThread(ClickEventThread);
            MonOpThread(a, b);
        }

        public void MonOpThread(string a, string b) {
            try {
                traceFen("Etape B : MonOpThread :: MonOpThread a=" + a + " b=" + b);
                if (ClickEventThread != null) {
                    traceFen("Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread");
                    ClickEventThread(a, b);
                }
            }
            catch (TargetException te) {
                traceFen("## Exception dans MonOpThread (TargetException):: Message [[" + te.Message + "]]");
            }
            catch (Exception e) {
                traceFen("## Exception dans MonOpThread :: " + e.Message);
            }
        }

        public void traceFen(string p) {
            tx.Text +=  p + "\r\n";
        }
    }
}


Resultat obtenu :

Si depuis le navigateur, je lance un appel à la monObj.FoncActiveThread('CHAPI','CHAPO') , j'obtiens bien les traces suivantes :
Etape A : FoncActiveThread :: a  =CHAPI b= CHAPO
Etape B : MonOpThread :: MonOpThread a=CHAPI b=CHAPO
Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread

l'événement est bien lancé et ma page HTML le capte bien.. nickel. :yaisse2:

Mais lorsque, toujours depuis le navigateur, je fais appel à monObj.demandeLance() , le composant va bien lancer dans un processus différent l'execution de la méthode ThreadLoop() de mon objet de type MonThreadHandle.

Depuis ce processus, sera alors appelé la même méthode que précedement (FoncActiveThread()) de l'objet "parent".

Le positionnement du handler est alors réalisé, mais lorsque je fais appel au même bout de code qui me permettait de réaliser l'envoi de l'évenement, une exception de type TargetException est alors lancée, indiquant "L'objet ne correspond pas au type cible." :(
Etape A : FoncActiveThread :: a =JOJO b=JUJU
Etape B : MonOpThread :: MonOpThread a=JOJO b=JUJU
Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread
## Exception dans MonOpThread (TargetException):: Message [[L'objet ne correspond pas au type cible.]]


Donc si quelqu'un aurait une petite explication sur l'erreur retournée, cela serait avec grand plaisir  :) .. d'autant que là .. j'essaie différents moyens . mais cela ne passe toujours pas ..

Merci d'avance pour votre attention .. et surtout à ceux qui auront lu ce looooong post.

1 réponse

Mediant Messages postés 2 Date d'inscription mercredi 20 février 2008 Statut Membre Dernière intervention 17 mars 2008
17 mars 2008 à 20:31
Bon .. je n'ai toujours pas compris ...  :roll:

Mais j'ai trouvé un autre moyen de réaliser cette opération.

Pour ceux que cela pourrait intéresser, je me suis passé de la classe MonThreadHandle que j'utilisais, et ai tout repris dans MyWindowControlAutre

Voici le code :

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.Reflection;

namespace ActiveXSourcingAutre {
    public delegate void ClickEventHandlerThread(string a, string b);
    [System.Runtime.InteropServices.GuidAttribute("9621A92C-3FBD-4be4-9153-51EEC1444507")]

    [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)]
    public interface ControlEventsAutre
    {
        [System.Runtime.InteropServices.DispIdAttribute(0x60035000)]
        void ClickEventThread(string a, string b);
    }

    [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)]
    public interface MonInterfaceAutre {
        [System.Runtime.InteropServices.DispIdAttribute(0x60060003)]
        void demandeLance();
        [System.Runtime.InteropServices.DispIdAttribute(0x60060007)]
        void FoncActiveThread(string a, string b);
    }

    [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None), System.Runtime.InteropServices.ComSourceInterfaces(typeof(ControlEventsAutre))]
    public class MyWindowControlAutre : System.Windows.Forms.UserControl, MonInterfaceAutre //, ComInteropControlInterface
    {
        System.Windows.Forms.TextBox tx = new TextBox();
        Thread t;

        event ActiveXSourcingAutre.ClickEventHandlerThread ClickEventThread;

        private void InitializeComponent() {
            this.Name = "MyWindowControlAutre";
        }

        public MyWindowControlAutre()
            : base() {
            initMyWindowControlAutre();
        }

        private void initMyWindowControlAutre() {
            tx.Text = "";
            Size = new System.Drawing.Size(700, 450);
            tx.Size = this.Size;
            tx.Multiline = true;
            tx.ScrollBars = ScrollBars.Vertical;
            tx.AcceptsReturn = true;
            tx.AcceptsTab = true;
            tx.WordWrap = true;
            this.Controls.Add(tx);
        }

        public void demandeLance() {
            Lance();
        }

        //[STAThread]
        void Lance() {
            t = null;
            try {
                t = new Thread(new ThreadStart(ThreadLoop));
                t.Start();                
            }
            catch {
                traceFen("Thead non lance");
                return;
            }
        }

        public void FoncActiveThread(string a, string b) {
            traceFen("Etape A : FoncActiveThread :: a=" + a + " b=" + b);
            ClickEventThread = new ClickEventHandlerThread(ClickEventThread);
            MonOpThread(a, b);
        }

        public void MonOpThread(string a, string b) {
            try {
                traceFen("Etape B : MonOpThread :: MonOpThread a=" + a + " b=" + b);
                if (ClickEventThread != null) {
                    traceFen("Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread");
                    ClickEventThread(a, b);
                }
            }
            catch (TargetException te) {
                traceFen("## Exception dans MonOpThread (TargetException):: Message [[" + te.Message + "]]");
            }
            catch (Exception e) {
                traceFen("## Exception dans MonOpThread :: " + e.Message);
            }
        }

        public void traceFen(string p) {
            tx.Text += p + "\r\n";
        }

        public void AffichageInterp() {
            object[] args = new object[2];
            args[0] = "JOJO";
            args[1] = "JUJU";
            Invoke(ClickEventThread, args);
        }

        public void ThreadLoop() {
            AffichageInterp();
        }
  
    }
}
0
Rejoignez-nous