2009-12-07 3 views
0

J'ai une application .NET contenant un WinForm. Ce WinForm contient un contrôle ActiveX non géré et quelques autres contrôles. Cette application fonctionne très bien en mode autonome. Maintenant, nous voulons publier une sorte d'interface afin que Winform puisse être utilisé à partir d'applications C++/MFC non gérées à l'aide de la fonctionnalité Interop. Les applications client afficheront ce formulaire de manière non modale. Lorsque l'utilisateur entre les détails, ceux-ci sont transmis au client à l'aide de la méthode source/puits d'événement COM (ou point de connexion).COM - .NET Interop - Winform à partir du client COM

J'ai suivi divers articles et l'une des méthode qui fonctionne pour nous est http://codebetter.com/blogs/peter.van.ooijen/archive/2005/06/03/64041.aspx

Mais si je commence à plus d'un fil de la même application cliente, la deuxième instance de forme émet des exceptions de violation d'accès parce que les Le contrôle ActiveX sur le formulaire s'attend à ce que le thread soit toujours un thread d'interface utilisateur (basé sur mon observation).

Pouvez-vous me dire quelle est la bonne façon d'exposer une fonctionnalité WinForm à des applications client non gérées via Interop?

Un grand merci

+0

Votre application WinForm STA ou MTA? –

+0

C'est un STA et j'ai un bon état d'appartement pour le fil que je crée. – byte

Répondre

1

L'article que vous vous donne lié toutes les informations dont vous avez besoin d'héberger correctement un formulaire dans une application non géré. Vous devriez chercher la source de l'AV ailleurs. Commencez par utiliser le débogueur. Vous pouvez le forcer à s'arrêter sur l'exception avec la boîte de dialogue Debug + Exceptions, Case à cocher Thrown.

L'exigence STA est presque toujours suffisante pour permettre à un contrôle ActiveX de fonctionner correctement dans une application multithread. Il fournit la garantie que tous les appels de méthode sont effectués sur le même thread dans lequel la coclasse a été créée. En d'autres termes, toutes les variables d'instance à l'intérieur de l'implémentation de la coclasse sont garanties d'être utilisées de manière thread-safe. Une garantie que vous n'avez pas ici est de savoir si le contrôle gère correctement l'état global. Les variables d'instance sont sûres, les variables globales ne le sont pas lorsque vous utilisez le contrôle dans différents threads. Une solution de contournement possible pour cela consiste à utiliser un seul thread au lieu d'un thread STA pour chaque instance de formulaire. C'est un peu difficile, vous aurez besoin d'une forme d'aide invisible qui gère le fil. Gardez-le en vie et créez de nouvelles instances de formulaire à l'aide de sa méthode Invoke().

Avant de vous y rendre, découvrez d'abord ce qui plante.

+0

Merci. Je crois que le contrôle activex nécessite explicitement un thread ui. Si j'instancie deux formes du thread ui principal cela fonctionne bien. Je regarde maintenant http://msdn.microsoft.com/fr-fr/library/ms229591(VS.80).aspx Avec les articles ci-dessus, je ne vois pas comment fermer la forme c'est montré en utilisant Show et non ShowDialog. Donc à partir de ma classe d'interopérabilité si j'appelle form.Fermer puis la méthode Dispose est appelée deux fois - une fois par Close qui appelle Dispose qui inturn appelle MyBase.Dispose qui appelle ac_ThreadExit (voir article) et dans cette routine un appel à Form.Dispose est fait explicitement . Toute aide avec ça? – byte

+0

Ok, clairement le contrôle a des problèmes avec l'état global. L'article que vous avez lié résout un problème différent. Celui que vous n'avez pas, vous pompez déjà votre propre boucle de message (Application.Run).Vous ne pouvez pas appeler la méthode Close() directement à partir de votre classe d'interopérabilité, elle doit être effectuée sur le bon thread. C'est pourquoi j'ai suggéré d'utiliser la forme d'assistant invisible pour que vous puissiez utiliser sa méthode Invoke(). –

+0

Merci. Je suis d'accord et j'ai observé le même comportement en appelant Close - les threads sont différents. Je vais essayer de mettre en place un formulaire d'aide invisible pour voir si cela résout les problèmes. – byte

1

Vous devez définir votre hôte C++/MFC pour utiliser apartment threading model pour l'objet COM C# forms. Cela sérialisera tous les appels sur le proxy via le thread d'origine qui a instancié l'objet COM. Vous devez également correctement marshal l'interface d'origine entre vos threads dans le code C++/MFC, en utilisant CoMarshalInterThreadInterfaceInStream et CoGetInterfaceAndReleaseStream

+0

Merci. J'ai fait cela mais je pense que le problème est avec le contrôle activeX. – byte

Questions connexes