我有一个COM服务器(C ++ / STA(基于MFC的应用程序))和一个COM客户端(C#/ MTA)。 COM服务器必须位于STA中,因为它是一个MFC应用程序(在这个问题上我别无选择)。客户端向服务器发出调用,服务器向客户端发出回调。这就是错误发生的地方(RPC_E_CANTCALLOUT_ININPUTSYNCCALL
)。我猜测服务器是否是MTA,这个问题永远不会出现,但遗憾的是,MFC的文档明确否认将公寓初始化为MTA。
有关如何解决此问题的任何想法?
我一直在想让服务器对象(我通过运行对象表公开的对象)住在自己的公寓(MTA)中。这是一个好主意,还是先尝试一些简单的东西?
更新
服务器对象只是指向应用程序中某些功能的精简界面。大多数情况下,它只是读取和写入内存位置,但有些情况下它会向应用程序中的各个窗口生成窗口消息。服务器对象本身不是整个应用程序。
答案 0 :(得分:12)
RPC_E_CANTCALLOUT_ININPUTSYNCCALL表示您尝试从处理程序中为通过SendMessage
发送的Windows消息进行编组的COM调用。这有助于避免某些死锁情况。您有许多选项,可以归结为“避免在SendMessage处理程序中调用COM”:
PostMessage
将消息排队给自己,并在发布的消息处理程序中,调用COM回调。 答案 1 :(得分:0)
无论我扭曲和转动多少,当我从客户端调用时,我都无法删除应用程序中的STA上下文。如果我在MTA中托管服务器对象并不重要,我仍然必须遵守COM的规则。在这种情况下,STA是一个非常讨厌的“惩教设施”。我很难过......
这让我走上了一条相当丑陋的道路,但它确实有效。我没有使用COM与客户端进行通信,而是将自己的通信路径滚动到承载服务器对象和回调引用的MTA。我基本上是通过设置一个调用队列(带有要发送的参数的STL容器)来创建自己的编组代码,MTA线程将其拾取并传递给客户端。然后将响应返回到响应初始调用的代码。使用Win32事件对象完成同步。
幸运的是,我不需要涉及很多回调,并且该机制的性质是静态的,并且仅用于我自己的目的(不会在生产环境中运行)。
Wheew ...有时候我想知道如果我选择成为一名木匠,生活会是怎样的。
答案 2 :(得分:0)
您可以在收到消息时创建计时器,然后在WM_TIMER下的TimerProc / WinProc中进行COM调用和进一步处理。这对我有用。