11
votes

COM L'appel sortant donne des résultats "Un appel sortant ne peut pas être effectué car l'application envoie un appel d'entrée-synchrone".

J'ai un serveur COM (C ++ / STA (application basée sur la MFC)) et un client COM (C # / MTA). Le serveur COM doit vivre dans une STA, car il s'agit d'une application MFC (je n'ai aucun choix dans cette affaire). Le client émet un appel au serveur et le serveur émet un rappel au client. C'est là que l'erreur se produit ( rpc_e_cantcallout_ininpupsyncccall ). Je suppose que si le serveur était un MTA, ce problème n'aurait jamais été découvert, mais malheureusement, la documentation relative à la MFC nie explicitement explicitement l'appartement en tant que MTA.

Des idées sur la façon de travailler autour de ce problème?

J'ai joué avec l'idée de laisser l'objet serveur (l'objet que j'expose via la table d'objets en cours d'exécution) en direct dans un appartement de son propre (MTA). Ce serait-il une bonne idée, ou existe-t-il quelque chose de plus simple à essayer d'abord?

mise à jour

L'objet serveur est juste une mince interface pointe vers certaines fonctions de l'application. La plupart du temps, il suffit de lire et écrit aux emplacements de mémoire, mais il existe des instances où elle génère des messages de fenêtre à diverses fenêtres de l'application. L'objet serveur lui-même n'est pas l'ensemble de l'application.


3 commentaires

La conséquence directe de violer les exigences de filetage de l'appartement. Pretonne de savoir comment il s'agissait, mais si le serveur nécessite un seul appartement fileté, vous feriez mieux de créer le RCW sur le côté C # sur un fil de STA.


L'application dans laquelle le serveur vit, nécessite une STA. L'objet serveur lui-même ne nécessite pas de STA. Certains appels vers le serveur généreront des messages de fenêtre envoyés à différentes fenêtres de l'application.


Que voulez-vous dire en créant le RCW sur le côté C #?


3 Réponses :


1
votes

Peu importe combien je tord et tourne, je ne peux pas me retirer du contexte de STA dans l'application lorsque je suis appelé à partir du client. Peu importe que j'hôte l'objet serveur dans un MTA, je reste doit obéir aux lois de COM. La STA est une "installation correctionnelle" vraiment désagréable dans ce cas. Je fais du mal ...

Cela m'a conduit à un chemin assez laid, mais cela fonctionne. Au lieu d'utiliser COM pour communiquer avec le client, je suis à la main sur ma propre voie de communication vers le MTA qui héberge l'objet serveur et les références de rappel. Je crée essentiellement mon propre code marshalling en mettant en place une file d'attente d'appel (conteneur STL avec des paramètres à envoyer), que le fil du MTA prend et offre au client. La réponse est ensuite renvoyée au code qui répond à l'appel initial. La synchronisation est effectuée à l'aide d'objets d'événement Win32.

Heureusement, il n'y a pas beaucoup de rappels que je dois couvrir et la nature du mécanisme est statique et ne sera utilisée que pour mes propres fins (ne sera pas exécutée dans un environnement de production).

wheew ... Parfois, je me demande quelle vie aurait été si j'ai choisi de devenir un charpentier à la place.


0 commentaires

17
votes

RPC_E_CANTCALLOTE_ININPUTSYNCCALL signifie que vous avez tenté de faire appel à un appel commercial de l'intérieur du gestionnaire pour un message Windows envoyé via sendMessage . C'est pour aider à éviter certaines situations d'impasse. Vous avez plusieurs options, qui font bouillir jusqu'à "éviter les appels de com dans un gestionnaire de sendmessage":


3 commentaires

J'ai fini par utiliser Point 1, car cela signifie que le moyen le plus simple de gérer la question à portée de main, car je n'ai pas beaucoup de rappels (trois au fur et à mesure de cela, et je ne vois pas ce chiffre en train de changer de fois de suite). Ce code d'automatisation que je travaille n'est pas un travail prioritaire, et je ne peux pas dépenser trop de temps et d'efforts. Surtout quand c'est une chose "en maison", je travaille sur. Toutefois, vos points sont très informatifs et je les garderai à l'esprit si je devais encore faire face à ce type de chose dans le code de production. Merci!


Dans WPF, je viens d'envelopper mon code autour de nouveau thread (nouveau threadstart (((() => { et })). Démarrer (); et voici!


@ ioanb7 vous da homme ou femme..nuez sûr! Cela a évité l'erreur de l'OP mentionnée dans Winforms.



0
votes

Vous pouvez créer une minuterie lorsque vous recevez le message, puis effectuez vos appels COM et un traitement ultérieur dans votre TimerProc / WinProC sous WM_TIMER. Cela fonctionne pour moi.


0 commentaires