遇到乍一看像 MT 问题的东西,但我试图详细了解 COM+ 使用的 STA 模型。
实际上,我有一个用 VB6 编写的遗留 COM+ 组件,它调用用 C++ 编写的本机(即非 COM)Win32 DLL。
遇到一些间歇性(并且无法在测试中重现)问题,我添加了一些调试代码以找出发生了什么,并发现当问题发生时,我在文件中交错了日志消息 - 所以它暗示 DLL被两个线程同时调用。
现在日志记录到基于 _getpid() 和 GetCurrentThreadId() 的每个线程文件,所以看起来当 C++ DLL 中的代码被调用时,它会同时在同一个线程上被调用两次。我对 STA 的理解表明,这可能是这种情况,因为 COM 将对象的各个实例编组到单个线程上,并随意挂起和恢复执行。
不幸的是,我不确定从这里去哪里。我读到我应该在 DllMain() 中调用 CoInitialiseEx() 来告诉 COM 这是一个 STA DLL,但其他地方说这仅对 COM DLL 有效,并且对本机 DLL 没有任何影响。唯一的其他选择是将 DLL 的某些部分包装为关键部分以序列化访问(承担对下巴造成的任何性能损失)。
我可以尝试重做 DLL,但没有共享状态或全局变量 - 一切都在局部变量中,所以理论上每个调用都应该有自己的堆栈,但我想知道 STA 模型是否基本上对此有一些奇怪的影响并且只是在与另一个调用相同的入口点重新进入已加载的 DLL。不幸的是,我不知道如何证明或测试这个理论。
问题基本上是:
- 当 STA COM+ 组件调用本机 DLL 时,STA 模型中没有任何内容可以防止活动“线程”被挂起并将控制权传递给 DLL 调用中间的另一个“线程”?
- CoInitialiseEx() 是否是解决此问题的正确方法?
- 如果 (1) 或 (2) 都不是“好的”假设,那会发生什么?