2010-10-11 3 views
2

Lors de la création d'un serveur COM hors processus en C#, comme indiqué dans l'exemple de code de Microsoft Tout-en-un: CSExeCOMServer, il semble difficile de contrôler le modèle de thread des objets créés dans le serveur (par un client).Contrôle du modèle de thread des objets COM servis par les serveurs de processus .NET

L'objet créé doit être en un STA en raison du fait qu'il utilise des objets WPF, et l'usine de elle est enregistrée comme démontré sur la ligne 95 de ExeCOMServer.cs et collé ci-dessous ...

private void PreMessageLoop() 
{ 
    // 
    // Register the COM class factories. 
    // 

    Guid clsidSimpleObj = new Guid(SimpleObject.ClassId); 

    // Register the SimpleObject class object 
    int hResult = COMNative.CoRegisterClassObject(
     ref clsidSimpleObj,     // CLSID to be registered 
     new SimpleObjectClassFactory(),  // Class factory 
     CLSCTX.LOCAL_SERVER,    // Context to run 
     REGCLS.MULTIPLEUSE | REGCLS.SUSPENDED, 
     out _cookieSimpleObj); 
    if (hResult != 0) 
    { 
     throw new ApplicationException(
     "CoRegisterClassObject failed w/err 0x" + hResult.ToString("X")); 
    } 

Toutefois, la fonction CreateInstance est toujours appelée dans un nouveau thread qui se trouve dans un MTA. Il ne semble pas important que le thread principal du serveur local soit marqué (et vérifié) comme un thread STA.

Tout le matériel sur le sujet qui a été trouvé suggère que l'appartement des objets créés doit correspondre à l'appartement du fil dans lequel l'usine a été enregistrée. En fait, cela semble être le cas lors de l'utilisation d'un serveur ATL COM (mélangé avec Managed C++ pour créer les objets), mais cette méthode semble injecter un nouveau thread dans le flux de travail dont les paramètres d'initialisation, en particulier le modèle COM , ne semble pas être modifiable. Est-ce que quelqu'un a résolu ce problème sans recourir à un serveur COM écrit en grande partie en code non managé.

+1

Pouah, je déteste * la merde qu'ils ont inventée. J'étais étroitement associé aux forums MSDN quand ils ont été embauchés en Chine. J'étais un mod communautaire à l'époque. La bibliothèque n'est pas du tout évaluée par des pairs, elle chevauche l'angle "à 55%". Surtout le gars appelé "Ge" est très dangereux pour son ignorance. Le modèle de thread du serveur est affecté par la façon dont le serveur initialise COM. Pas le client. –

+0

Merci pour la perspicacité ... mais l'exemple semble fonctionner assez bien pour ce qu'il fait. Il n'est pas techniquement incorrect d'avoir un MTA initialiser notre objet. La partie confuse est que le thread principal du _SERVER_ appartient à un STA, pourtant le framework (COM, OLE, quel que soit) crée un nouveau thread, dans le serveur, qui est dans le MTA du serveur, pour appeler CreateInstance de notre Factory. – Steven

Répondre

2

Nous avons une situation très similaire récemment lors de la configuration d'une application WinForm pour héberger des objets pour l'interopérabilité 64 bits. Le thread d'interface utilisateur entre le STA au démarrage (avec l'attribut STAThread). Nous n'avons pas tardé à découvrir que tous les constructeurs étaient exécutés dans le thread d'interface utilisateur (STA), mais que toutes les autres méthodes étaient exécutées dans un thread de travail (MTA) créé par .Net. Ce n'est pas vraiment le MTA qui est le problème, mais nous avons des méthodes qui accèdent à l'interface utilisateur et le fait qu'elles sont toujours exécutées dans un thread de travail qui nous perturbe. Bien que nous ne puissions pas comprendre comment forcer Net à marier les appels au thread UI (STA), nous avons trouvé une astuce très sale impliquant ContextBoundObject et l'interception de méthode. Je ne vais pas entrer dans les détails, mais vous pouvez jeter un oeil à System.Runtime.Remoting.Messaging et System.Runtime.Remoting.Contexts namespaces. L'idée est de tromper le CCW en pensant un proxy transparent en tant qu'objet interop, et nous intercepterons chaque invocation au proxy, passerons le message au thread d'interface utilisateur, puis traduirons le message en appel de méthode. Sale? Oui. Performance? Très mauvais. Mais ça marche.

Si vous souhaitez voir le code d'interception de la méthode, vous pouvez m'envoyer un email.

Questions connexes